~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to ogr/ogr_srs_proj4.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: ogr_srs_proj4.cpp 18034 2009-11-15 20:13:38Z rouault $
 
2
 * $Id: ogr_srs_proj4.cpp 23620 2011-12-20 23:14:29Z rouault $
3
3
 *
4
4
 * Project:  OpenGIS Simple Features Reference Implementation
5
5
 * Purpose:  OGRSpatialReference interface to PROJ.4.
33
33
 
34
34
extern int EPSGGetWGS84Transform( int nGeogCS, double *padfTransform );
35
35
 
36
 
CPL_CVSID("$Id: ogr_srs_proj4.cpp 18034 2009-11-15 20:13:38Z rouault $");
 
36
CPL_CVSID("$Id: ogr_srs_proj4.cpp 23620 2011-12-20 23:14:29Z rouault $");
37
37
 
38
38
/* -------------------------------------------------------------------- */
39
39
/*      The following list comes from osrs/proj/src/pj_ellps.c          */
105
105
    { "OSGB36", "OSGB_1936", 4277, 6277}
106
106
};
107
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
 
108
133
static const char* OGRGetProj4Datum(const char* pszDatum,
109
134
                                    int nEPSGDatum)
110
135
{
120
145
    return NULL;
121
146
}
122
147
 
 
148
static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
 
149
{
 
150
    unsigned int i;
 
151
    for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
 
152
    {
 
153
        if (EQUAL(pszProj4PMName, ogr_pj_pms[i].pszProj4PMName))
 
154
        {
 
155
            return &ogr_pj_pms[i];
 
156
        }
 
157
    }
 
158
    return NULL;
 
159
}
 
160
 
 
161
static const OGRProj4PM* OGRGetProj4PMFromCode(int nPMCode)
 
162
{
 
163
    unsigned int i;
 
164
    for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
 
165
    {
 
166
        if (nPMCode == ogr_pj_pms[i].nPMCode)
 
167
        {
 
168
            return &ogr_pj_pms[i];
 
169
        }
 
170
    }
 
171
    return NULL;
 
172
}
 
173
 
 
174
static const OGRProj4PM* OGRGetProj4PMFromVal(double dfVal)
 
175
{
 
176
    unsigned int i;
 
177
    for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
 
178
    {
 
179
        if (fabs(dfVal - CPLDMSToDec(ogr_pj_pms[i].pszFromGreenwich)) < 1e-10)
 
180
        {
 
181
            return &ogr_pj_pms[i];
 
182
        }
 
183
    }
 
184
    return NULL;
 
185
}
 
186
 
123
187
/************************************************************************/
124
188
/*                          OSRProj4Tokenize()                          */
125
189
/*                                                                      */
360
424
 
361
425
    if( pszPM != NULL )
362
426
    {
363
 
        if( EQUAL(pszPM,"lisbon") )
364
 
        {
365
 
            dfFromGreenwich = CPLDMSToDec( "9d07'54.862\"W" );
366
 
            nPMCode = 8902;
367
 
        }
368
 
        else if( EQUAL(pszPM,"paris") )
369
 
        {
370
 
            dfFromGreenwich = CPLDMSToDec( "2d20'14.025\"E" );
371
 
            nPMCode = 8903;
372
 
        }
373
 
        else if( EQUAL(pszPM,"bogota") )
374
 
        {
375
 
            dfFromGreenwich = CPLDMSToDec( "74d04'51.3\"W" );
376
 
            nPMCode = 8904;
377
 
        }
378
 
        else if( EQUAL(pszPM,"madrid") )
379
 
        {
380
 
            dfFromGreenwich = CPLDMSToDec( "3d41'16.48\"W" );
381
 
            nPMCode = 8905;
382
 
        }
383
 
        else if( EQUAL(pszPM,"rome") )
384
 
        {
385
 
            dfFromGreenwich = CPLDMSToDec( "12d27'8.4\"E" );
386
 
            nPMCode = 8906;
387
 
        }
388
 
        else if( EQUAL(pszPM,"bern") )
389
 
        {
390
 
            dfFromGreenwich = CPLDMSToDec( "7d26'22.5\"E" );
391
 
            nPMCode = 8907;
392
 
        }
393
 
        else if( EQUAL(pszPM,"jakarta") )
394
 
        {
395
 
            dfFromGreenwich = CPLDMSToDec( "106d48'27.79\"E" );
396
 
            nPMCode = 8908;
397
 
        }
398
 
        else if( EQUAL(pszPM,"ferro") )
399
 
        {
400
 
            dfFromGreenwich = CPLDMSToDec( "17d40'W" );
401
 
            nPMCode = 8909;
402
 
        }
403
 
        else if( EQUAL(pszPM,"brussels") )
404
 
        {
405
 
            dfFromGreenwich = CPLDMSToDec( "4d22'4.71\"E" );
406
 
            nPMCode = 8910;
407
 
        }
408
 
        else if( EQUAL(pszPM,"stockholm") )
409
 
        {
410
 
            dfFromGreenwich = CPLDMSToDec( "18d3'29.8\"E" );
411
 
            nPMCode = 8911;
412
 
        }
413
 
        else if( EQUAL(pszPM,"athens") )
414
 
        {
415
 
            dfFromGreenwich = CPLDMSToDec( "23d42'58.815\"E" );
416
 
            nPMCode = 8912;
417
 
        }
418
 
        else if( EQUAL(pszPM,"oslo") )
419
 
        {
420
 
            dfFromGreenwich = CPLDMSToDec( "10d43'22.5\"E" );
421
 
            nPMCode = 8913;
 
427
        const OGRProj4PM* psProj4PM = OGRGetProj4PMFromProj4Name(pszPM);
 
428
        if (psProj4PM)
 
429
        {
 
430
            dfFromGreenwich = CPLDMSToDec(psProj4PM->pszFromGreenwich);
 
431
            pszPM = psProj4PM->pszWKTPMName;
 
432
            nPMCode = psProj4PM->nPMCode;
422
433
        }
423
434
        else
424
435
        {
445
456
    {
446
457
    }
447
458
    
 
459
    else if( EQUAL(pszProj,"geocent") )
 
460
    {
 
461
        SetGeocCS( "Geocentric" );
 
462
    }
 
463
    
448
464
    else if( EQUAL(pszProj,"bonne") )
449
465
    {
450
466
        SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ), 
479
495
 
480
496
    else if( EQUAL(pszProj,"tmerc") )
481
497
    {
482
 
        SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
483
 
               OSR_GDV( papszNV, "lon_0", 0.0 ), 
484
 
               OSR_GDV( papszNV, "k", 1.0 ), 
485
 
               OSR_GDV( papszNV, "x_0", 0.0 ), 
486
 
               OSR_GDV( papszNV, "y_0", 0.0 ) );
 
498
        const char *pszAxis = CSLFetchNameValue( papszNV, "axis" );
 
499
 
 
500
        if( pszAxis == NULL || !EQUAL(pszAxis,"wsu") )
 
501
            SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
 
502
                   OSR_GDV( papszNV, "lon_0", 0.0 ), 
 
503
                   OSR_GDV( papszNV, "k", 1.0 ), 
 
504
                   OSR_GDV( papszNV, "x_0", 0.0 ), 
 
505
                   OSR_GDV( papszNV, "y_0", 0.0 ) );
 
506
        else
 
507
            SetTMSO( OSR_GDV( papszNV, "lat_0", 0.0 ), 
 
508
                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
 
509
                     OSR_GDV( papszNV, "k", 1.0 ), 
 
510
                     OSR_GDV( papszNV, "x_0", 0.0 ), 
 
511
                     OSR_GDV( papszNV, "y_0", 0.0 ) );
487
512
    }
488
513
 
489
514
    else if( EQUAL(pszProj,"utm") )
531
556
               OSR_GDV( papszNV, "y_0", 0.0 ) );
532
557
    }
533
558
 
534
 
    else if( EQUALN(pszProj,"stere",5) /* mostly sterea */
535
 
             && CSLFetchNameValue(papszNV,"k") != NULL )
 
559
    else if( EQUAL(pszProj,"sterea") )
536
560
    {
537
561
        SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
538
562
               OSR_GDV( papszNV, "lon_0", 0.0 ), 
545
569
    {
546
570
        SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
547
571
                          OSR_GDV( papszNV, "lon_0", 0.0 ), 
548
 
                          1.0, 
 
572
                          OSR_GDV( papszNV, "k", 1.0 ),  
549
573
                          OSR_GDV( papszNV, "x_0", 0.0 ), 
550
574
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
551
575
    }
693
717
               OSR_GDV( papszNV, "y_0", 0.0 ) );
694
718
    }
695
719
 
 
720
    else if( EQUAL(pszProj,"igh") )
 
721
    {
 
722
        SetIGH();
 
723
    }
 
724
 
696
725
    else if( EQUAL(pszProj,"geos") )
697
726
    {
698
727
        SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
730
759
        SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
731
760
                OSR_GDV( papszNV, "lonc", 0.0 ), 
732
761
                OSR_GDV( papszNV, "alpha", 0.0 ), 
733
 
                0.0, /* ??? */
 
762
                OSR_GDV( papszNV, "gamma", 0.0 ), 
734
763
                OSR_GDV( papszNV, "k", 1.0 ), 
735
764
                OSR_GDV( papszNV, "x_0", 0.0 ), 
736
765
                OSR_GDV( papszNV, "y_0", 0.0 ) );
932
961
        {
933
962
            dfSemiMinor = OSR_GDV( papszNV, "b", -1.0 );
934
963
            dfInvFlattening = OSR_GDV( papszNV, "rf", -1.0 );
 
964
            if ( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
 
965
            {
 
966
                double dfFlattening = OSR_GDV( papszNV, "f", -1.0 );
 
967
                if ( dfFlattening == 0.0 )
 
968
                    dfSemiMinor = dfSemiMajor;
 
969
                else if ( dfFlattening != -1.0 )
 
970
                    dfInvFlattening = 1.0 / dfFlattening;
 
971
            }
935
972
        }
936
973
        
937
974
        if( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
987
1024
    }
988
1025
 
989
1026
/* -------------------------------------------------------------------- */
 
1027
/*      Handle nadgrids via an extension node.                          */
 
1028
/* -------------------------------------------------------------------- */
 
1029
    pszValue = CSLFetchNameValue(papszNV, "nadgrids");
 
1030
    if( pszValue != NULL )
 
1031
    {
 
1032
        SetExtension( "DATUM", "PROJ4_GRIDS", pszValue );
 
1033
    }
 
1034
 
 
1035
/* -------------------------------------------------------------------- */
990
1036
/*      Linear units translation                                        */
991
1037
/* -------------------------------------------------------------------- */
992
 
    if( IsProjected() || IsLocal() )
 
1038
    if( IsProjected() || IsLocal() || IsGeocentric() )
993
1039
    {
994
1040
        pszValue = CSLFetchNameValue(papszNV, "to_meter");
995
1041
 
1046
1092
        }        
1047
1093
    }
1048
1094
 
 
1095
/* -------------------------------------------------------------------- */
 
1096
/*      Handle geoidgrids via an extension node and COMPD_CS.           */
 
1097
/* -------------------------------------------------------------------- */
 
1098
    pszValue = CSLFetchNameValue(papszNV, "geoidgrids");
 
1099
    if( pszValue != NULL )
 
1100
    {
 
1101
        OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
 
1102
        
 
1103
        Clear();
 
1104
        
 
1105
        CPLString osName = poHorizSRS->GetChild(0)->GetValue();
 
1106
        osName += " + ";
 
1107
        osName += "Unnamed Vertical Datum";
 
1108
        
 
1109
        SetNode( "COMPD_CS", osName );
 
1110
        GetRoot()->AddChild( poHorizSRS );
 
1111
 
 
1112
        OGR_SRSNode *poVertSRS;
 
1113
        
 
1114
        poVertSRS = new OGR_SRSNode( "VERT_CS" );
 
1115
        GetRoot()->AddChild( poVertSRS );
 
1116
        poVertSRS->AddChild( new OGR_SRSNode( "Unnamed" ) );
 
1117
 
 
1118
        CPLString osTarget = GetRoot()->GetValue();
 
1119
        osTarget += "|VERT_CS|VERT_DATUM";
 
1120
 
 
1121
        SetNode( osTarget, "Unnamed" );
 
1122
        
 
1123
        poVertSRS->GetChild(1)->AddChild( new OGR_SRSNode( "2005" ) );
 
1124
        SetExtension( osTarget, "PROJ4_GRIDS", pszValue );
 
1125
 
 
1126
        OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
 
1127
 
 
1128
        poAxis->AddChild( new OGR_SRSNode( "Up" ) );
 
1129
        poAxis->AddChild( new OGR_SRSNode( "UP" ) );
 
1130
        
 
1131
        poVertSRS->AddChild( poAxis );
 
1132
    }
 
1133
 
 
1134
/* -------------------------------------------------------------------- */
 
1135
/*      Handle vertical units.                                          */
 
1136
/* -------------------------------------------------------------------- */
 
1137
    if( GetRoot()->GetNode( "VERT_CS" ) != NULL )
 
1138
    {
 
1139
        const char *pszUnitName = NULL;
 
1140
        const char *pszUnitConv = NULL;
 
1141
 
 
1142
        pszValue = CSLFetchNameValue(papszNV, "vto_meter");
 
1143
 
 
1144
        if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
 
1145
        {
 
1146
            double dfValue = CPLAtofM(pszValue);
 
1147
 
 
1148
            if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
 
1149
            {
 
1150
                pszUnitName = SRS_UL_US_FOOT;
 
1151
                pszUnitConv = SRS_UL_US_FOOT_CONV;
 
1152
            }
 
1153
            else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
 
1154
            {
 
1155
                pszUnitName = SRS_UL_FOOT;
 
1156
                pszUnitConv = SRS_UL_FOOT_CONV;
 
1157
            }
 
1158
            else if( dfValue == 1.0 )
 
1159
            {
 
1160
                pszUnitName = SRS_UL_METER;
 
1161
                pszUnitConv = "1.0";
 
1162
            }
 
1163
            else
 
1164
            {
 
1165
                pszUnitName = "unknown";
 
1166
                pszUnitConv = pszValue;
 
1167
            }
 
1168
        }
 
1169
        else if( (pszValue = CSLFetchNameValue(papszNV, "vunits")) != NULL )
 
1170
        {
 
1171
            if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") )
 
1172
            {
 
1173
                pszUnitName = SRS_UL_METER;
 
1174
                pszUnitConv = "1.0";
 
1175
            }
 
1176
            else if( EQUAL(pszValue,"us-ft" ) )
 
1177
            {
 
1178
                pszUnitName = SRS_UL_US_FOOT;
 
1179
                pszUnitConv = SRS_UL_US_FOOT_CONV;
 
1180
            }
 
1181
            else if( EQUAL(pszValue,"ft" ) )
 
1182
            {
 
1183
                pszUnitName = SRS_UL_FOOT;
 
1184
                pszUnitConv = SRS_UL_FOOT_CONV;
 
1185
            }
 
1186
            else if( EQUAL(pszValue,"yd" ) )
 
1187
            {
 
1188
                pszUnitName = "Yard";
 
1189
                pszUnitConv = "0.9144";
 
1190
            }
 
1191
            else if( EQUAL(pszValue,"us-yd" ) )
 
1192
            {
 
1193
                pszUnitName = "US Yard";
 
1194
                pszUnitConv = "0.914401828803658";
 
1195
            }
 
1196
        }
 
1197
 
 
1198
        if( pszUnitName != NULL )
 
1199
        {
 
1200
            OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
 
1201
            OGR_SRSNode *poUnits; 
 
1202
 
 
1203
            poUnits = new OGR_SRSNode( "UNIT" );
 
1204
            poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
 
1205
            poUnits->AddChild( new OGR_SRSNode( pszUnitConv ) );
 
1206
            
 
1207
            poVERT_CS->AddChild( poUnits );
 
1208
        }
 
1209
    }
1049
1210
 
1050
1211
/* -------------------------------------------------------------------- */
1051
1212
/*      do we want to insert a PROJ.4 EXTENSION item?                   */
1058
1219
    return OGRERR_NONE;
1059
1220
}
1060
1221
 
 
1222
/************************************************************************/
 
1223
/*                           LinearToProj4()                            */
 
1224
/************************************************************************/
 
1225
 
 
1226
static const char *LinearToProj4( double dfLinearConv, 
 
1227
                                  const char *pszLinearUnits )
 
1228
 
 
1229
{
 
1230
    if( dfLinearConv == 1.0 )
 
1231
        return "m";
 
1232
 
 
1233
    else if( dfLinearConv == 1000.0 )
 
1234
        return "km";
 
1235
    
 
1236
    else if( dfLinearConv == 0.0254 )
 
1237
        return "in";
 
1238
    
 
1239
    else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
 
1240
             || fabs(dfLinearConv - atof(SRS_UL_FOOT_CONV)) < 0.000000001 )
 
1241
        return "ft";
 
1242
    
 
1243
    else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
 
1244
        return "yd";
 
1245
 
 
1246
    else if( dfLinearConv == 0.914401828803658 )
 
1247
        return "us-yd";
 
1248
    
 
1249
    else if( dfLinearConv == 0.001 )
 
1250
        return "mm";
 
1251
    
 
1252
    else if( dfLinearConv == 0.01 )
 
1253
        return "cm";
 
1254
 
 
1255
    else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
 
1256
             || fabs(dfLinearConv - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
 
1257
        return "us-ft";
 
1258
 
 
1259
    else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
 
1260
        return "kmi";
 
1261
 
 
1262
    else if( EQUAL(pszLinearUnits,"Mile") 
 
1263
             || EQUAL(pszLinearUnits,"IMILE") )
 
1264
        return "mi";
 
1265
    else
 
1266
        return NULL;
 
1267
}
 
1268
 
1061
1269
 
1062
1270
/************************************************************************/
1063
1271
/*                          OSRExportToProj4()                          */
1082
1290
/*                           exportToProj4()                            */
1083
1291
/************************************************************************/
1084
1292
 
 
1293
#define SAFE_PROJ4_STRCAT(szNewStr)  do { \
 
1294
    if(CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4)) { \
 
1295
        CPLError(CE_Failure, CPLE_AppDefined, "String overflow when formatting proj.4 string"); \
 
1296
        *ppszProj4 = CPLStrdup(""); \
 
1297
        return OGRERR_FAILURE; \
 
1298
    } } while(0);
 
1299
 
1085
1300
/**
1086
1301
 * \brief Export coordinate system in PROJ.4 format.
1087
1302
 *
1148
1363
    {
1149
1364
        sprintf( szProj4+strlen(szProj4), "+proj=longlat " );
1150
1365
    }
 
1366
    else if( IsGeocentric() )
 
1367
    {
 
1368
        sprintf( szProj4+strlen(szProj4), "+proj=geocent " );
 
1369
    }
 
1370
 
1151
1371
    else if( pszProjection == NULL && !IsGeographic() )
1152
1372
    {
1153
1373
        // LOCAL_CS, or incompletely initialized coordinate systems.
1157
1377
    else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
1158
1378
    {
1159
1379
        sprintf( szProj4+strlen(szProj4),
1160
 
           "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
 
1380
                 "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
1161
1381
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1162
1382
                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
1163
1383
                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
1167
1387
    else if( EQUAL(pszProjection,SRS_PT_BONNE) )
1168
1388
    {
1169
1389
        sprintf( szProj4+strlen(szProj4),
1170
 
           "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
 
1390
                 "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
1171
1391
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1172
1392
                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
1173
1393
                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
1177
1397
    else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
1178
1398
    {
1179
1399
        sprintf( szProj4+strlen(szProj4),
1180
 
           "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
 
1400
                 "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
1181
1401
                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
1182
1402
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1183
1403
                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
1215
1435
        }            
1216
1436
        else
1217
1437
            sprintf( szProj4+strlen(szProj4),
1218
 
             "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
 
1438
                     "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
 
1439
                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
 
1440
                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
 
1441
                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
 
1442
                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
 
1443
                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
 
1444
    }
 
1445
 
 
1446
    else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
 
1447
    {
 
1448
        sprintf( szProj4+strlen(szProj4),
 
1449
                 "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g +axis=wsu ",
1219
1450
                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
1220
1451
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1221
1452
                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
1251
1482
    else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
1252
1483
    {
1253
1484
        sprintf( szProj4+strlen(szProj4),
1254
 
           "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
 
1485
                 "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
1255
1486
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1256
1487
                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
1257
1488
                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
1261
1492
    else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
1262
1493
    {
1263
1494
        sprintf( szProj4+strlen(szProj4),
1264
 
         "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
 
1495
                 "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
1265
1496
//         "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
1266
1497
                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
1267
1498
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1273
1504
    else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
1274
1505
    {
1275
1506
        sprintf( szProj4+strlen(szProj4),
1276
 
           "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
 
1507
                 "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
1277
1508
                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
1278
1509
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1279
1510
                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
1316
1547
 
1317
1548
    else if( EQUAL(pszProjection,SRS_PT_GAUSSSCHREIBERTMERCATOR) )
1318
1549
    {
1319
 
      sprintf( szProj4+strlen(szProj4),
1320
 
               "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g"
1321
 
               " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
1322
 
               GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-21.116666667),
1323
 
               GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,55.53333333309),
1324
 
               GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
1325
 
               GetNormProjParm(SRS_PP_FALSE_EASTING,160000.000),
1326
 
               GetNormProjParm(SRS_PP_FALSE_NORTHING,50000.000) );
 
1550
        sprintf( szProj4+strlen(szProj4),
 
1551
                 "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g"
 
1552
                 " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
 
1553
                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-21.116666667),
 
1554
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,55.53333333309),
 
1555
                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
 
1556
                 GetNormProjParm(SRS_PP_FALSE_EASTING,160000.000),
 
1557
                 GetNormProjParm(SRS_PP_FALSE_NORTHING,50000.000) );
1327
1558
    }
1328
1559
 
1329
1560
    else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
1382
1613
    else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
1383
1614
    {
1384
1615
        sprintf( szProj4+strlen(szProj4),
1385
 
                "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
 
1616
                 "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
1386
1617
                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
1387
1618
                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
1388
1619
                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
1520
1751
                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
1521
1752
    }
1522
1753
 
 
1754
    else if( EQUAL(pszProjection,SRS_PT_IGH) )
 
1755
    {
 
1756
        sprintf( szProj4+strlen(szProj4), "+proj=igh " );
 
1757
    }
 
1758
 
1523
1759
    else if( EQUAL(pszProjection,SRS_PT_GEOSTATIONARY_SATELLITE) )
1524
1760
    {
1525
1761
        sprintf( szProj4+strlen(szProj4),
1531
1767
    }
1532
1768
 
1533
1769
    else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
1534
 
         || EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
 
1770
             || EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
1535
1771
    {
1536
1772
        sprintf( szProj4+strlen(szProj4),
1537
1773
                 "+proj=lcc +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
1559
1795
 
1560
1796
    else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
1561
1797
    {
1562
 
        /* not clear how ProjParm[3] - angle from rectified to skewed grid -
1563
 
           should be applied ... see the +not_rot flag for PROJ.4.
1564
 
           Just ignoring for now. */
1565
 
 
1566
1798
        /* special case for swiss oblique mercator : see bug 423 */
1567
1799
        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001 
1568
1800
            && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
1587
1819
                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
1588
1820
                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
1589
1821
                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
 
1822
 
 
1823
            // RSO variant - http://trac.osgeo.org/proj/ticket/62
 
1824
            // Note that gamma is only supported by PROJ 4.8.0 and later.
 
1825
            if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
 
1826
            {
 
1827
                sprintf( szProj4+strlen(szProj4), "+gamma=%.16g ",
 
1828
                         GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
 
1829
            }
1590
1830
        }
1591
1831
    }
1592
1832
 
1823
2063
    {
1824
2064
        pszPROJ4Ellipse = "WGS84";
1825
2065
    }
1826
 
    else if( EQUAL(pszDatum,"North_American_Datum_1927") )
 
2066
    else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1927") )
1827
2067
    {
1828
2068
//        pszPROJ4Ellipse = "clrk66:+datum=nad27"; /* NAD 27 */
1829
2069
        pszPROJ4Ellipse = "clrk66";
1830
2070
    }
1831
 
    else if( EQUAL(pszDatum,"North_American_Datum_1983") )
 
2071
    else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1983") )
1832
2072
    {
1833
2073
//        pszPROJ4Ellipse = "GRS80:+datum=nad83";       /* NAD 83 */
1834
2074
        pszPROJ4Ellipse = "GRS80";
1835
2075
    }
1836
 
    
 
2076
 
 
2077
    char szEllipseDef[128];
 
2078
 
1837
2079
    if( pszPROJ4Ellipse == NULL )
1838
 
        sprintf( szProj4+strlen(szProj4), "+a=%.16g +b=%.16g ",
 
2080
        sprintf( szEllipseDef, "+a=%.16g +b=%.16g ",
1839
2081
                 GetSemiMajor(), GetSemiMinor() );
1840
2082
    else
1841
 
        sprintf( szProj4+strlen(szProj4), "+ellps=%s ",
 
2083
        sprintf( szEllipseDef, "+ellps=%s ",
1842
2084
                 pszPROJ4Ellipse );
1843
2085
 
1844
2086
/* -------------------------------------------------------------------- */
1851
2093
    const char *pszAuthority;
1852
2094
    int nEPSGGeogCS = -1;
1853
2095
    const char *pszGeogCSAuthority;
 
2096
    const char *pszProj4Grids = GetExtension( "DATUM", "PROJ4_GRIDS" );
1854
2097
 
1855
2098
    pszAuthority = GetAuthorityName( "DATUM" );
1856
2099
 
1866
2109
        /* nothing */;
1867
2110
 
1868
2111
    else if( EQUAL(pszDatum,SRS_DN_NAD27) || nEPSGDatum == 6267 )
1869
 
        pszPROJ4Datum = "+datum=NAD27";
 
2112
        pszPROJ4Datum = "NAD27";
1870
2113
 
1871
2114
    else if( EQUAL(pszDatum,SRS_DN_NAD83) || nEPSGDatum == 6269 )
1872
 
        pszPROJ4Datum = "+datum=NAD83";
 
2115
        pszPROJ4Datum = "NAD83";
1873
2116
 
1874
2117
    else if( EQUAL(pszDatum,SRS_DN_WGS84) || nEPSGDatum == 6326 )
1875
 
        pszPROJ4Datum = "+datum=WGS84";
 
2118
        pszPROJ4Datum = "WGS84";
1876
2119
 
1877
2120
    else if( (pszPROJ4Datum = OGRGetProj4Datum(pszDatum, nEPSGDatum)) != NULL )
1878
2121
    {
1879
 
        strcat( szProj4, "+datum=" );
1880
 
        /* The datum name contained in pszPROJ4Datum will be appended below */
1881
 
    }
1882
 
 
1883
 
    else if( poTOWGS84 != NULL )
1884
 
    {
1885
 
        int bOverflow = FALSE;
1886
 
        int iChild;
1887
 
        for(iChild=0;iChild<poTOWGS84->GetChildCount() && !bOverflow;iChild++)
 
2122
        /* nothing */
 
2123
    }
 
2124
 
 
2125
    if( pszProj4Grids != NULL )
 
2126
    {
 
2127
        SAFE_PROJ4_STRCAT( szEllipseDef );
 
2128
        szEllipseDef[0] = '\0';
 
2129
        SAFE_PROJ4_STRCAT( "+nadgrids=" );
 
2130
        SAFE_PROJ4_STRCAT( pszProj4Grids );
 
2131
        SAFE_PROJ4_STRCAT(  " " );
 
2132
        pszPROJ4Datum = NULL;
 
2133
    }
 
2134
 
 
2135
    if( pszPROJ4Datum == NULL 
 
2136
        || CSLTestBoolean(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84", "YES")) )
 
2137
    {
 
2138
        if( poTOWGS84 != NULL )
1888
2139
        {
1889
 
            if (strlen(poTOWGS84->GetChild(iChild)->GetValue()) > 24)
1890
 
                bOverflow = TRUE;
 
2140
            int iChild;
 
2141
            if( poTOWGS84->GetChildCount() >= 3
 
2142
                && (poTOWGS84->GetChildCount() < 7 
 
2143
                    || (EQUAL(poTOWGS84->GetChild(3)->GetValue(),"")
 
2144
                        && EQUAL(poTOWGS84->GetChild(4)->GetValue(),"")
 
2145
                        && EQUAL(poTOWGS84->GetChild(5)->GetValue(),"")
 
2146
                        && EQUAL(poTOWGS84->GetChild(6)->GetValue(),""))) )
 
2147
            {
 
2148
                SAFE_PROJ4_STRCAT( szEllipseDef );
 
2149
                szEllipseDef[0] = '\0';
 
2150
                SAFE_PROJ4_STRCAT( "+towgs84=");
 
2151
                for(iChild = 0; iChild < 3; iChild ++)
 
2152
                {
 
2153
                    if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
 
2154
                    SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
 
2155
                }
 
2156
                SAFE_PROJ4_STRCAT( " " );
 
2157
                pszPROJ4Datum = NULL;
 
2158
            }
 
2159
            else if( poTOWGS84->GetChildCount() >= 7)
 
2160
            {
 
2161
                SAFE_PROJ4_STRCAT( szEllipseDef );
 
2162
                szEllipseDef[0] = '\0';
 
2163
                SAFE_PROJ4_STRCAT( "+towgs84=");
 
2164
                for(iChild = 0; iChild < 7; iChild ++)
 
2165
                {
 
2166
                    if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
 
2167
                    SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
 
2168
                }
 
2169
                SAFE_PROJ4_STRCAT( " " );
 
2170
                pszPROJ4Datum = NULL;
 
2171
            }
1891
2172
        }
1892
2173
        
1893
 
        if( !bOverflow && poTOWGS84->GetChildCount() > 2
1894
 
            && (poTOWGS84->GetChildCount() < 6 
1895
 
                || (EQUAL(poTOWGS84->GetChild(3)->GetValue(),"")
1896
 
                && EQUAL(poTOWGS84->GetChild(4)->GetValue(),"")
1897
 
                && EQUAL(poTOWGS84->GetChild(5)->GetValue(),"")
1898
 
                && EQUAL(poTOWGS84->GetChild(6)->GetValue(),""))) )
1899
 
        {
1900
 
            sprintf( szTOWGS84, "+towgs84=%s,%s,%s",
1901
 
                     poTOWGS84->GetChild(0)->GetValue(),
1902
 
                     poTOWGS84->GetChild(1)->GetValue(),
1903
 
                     poTOWGS84->GetChild(2)->GetValue() );
1904
 
            pszPROJ4Datum = szTOWGS84;
1905
 
        }
1906
 
        else if( !bOverflow && poTOWGS84->GetChildCount() > 6)
1907
 
        {
1908
 
            sprintf( szTOWGS84, "+towgs84=%s,%s,%s,%s,%s,%s,%s",
1909
 
                     poTOWGS84->GetChild(0)->GetValue(),
1910
 
                     poTOWGS84->GetChild(1)->GetValue(),
1911
 
                     poTOWGS84->GetChild(2)->GetValue(),
1912
 
                     poTOWGS84->GetChild(3)->GetValue(),
1913
 
                     poTOWGS84->GetChild(4)->GetValue(),
1914
 
                     poTOWGS84->GetChild(5)->GetValue(),
1915
 
                     poTOWGS84->GetChild(6)->GetValue() );
1916
 
            pszPROJ4Datum = szTOWGS84;
1917
 
        }
1918
 
    }
 
2174
        // If we don't know the datum, trying looking up TOWGS84 parameters
 
2175
        // based on the EPSG GCS code.
 
2176
        else if( nEPSGGeogCS != -1 && pszPROJ4Datum == NULL )
 
2177
        {
 
2178
            double padfTransform[7];
 
2179
            if( EPSGGetWGS84Transform( nEPSGGeogCS, padfTransform ) )
 
2180
            {
 
2181
                sprintf( szTOWGS84, "+towgs84=%.16g,%.16g,%.16g,%.16g,%.16g,%.16g,%.16g",
 
2182
                         padfTransform[0],
 
2183
                         padfTransform[1],
 
2184
                         padfTransform[2],
 
2185
                         padfTransform[3],
 
2186
                         padfTransform[4],
 
2187
                         padfTransform[5],
 
2188
                         padfTransform[6] );
 
2189
                SAFE_PROJ4_STRCAT( szEllipseDef );
 
2190
                szEllipseDef[0] = '\0';
1919
2191
 
1920
 
    else if( nEPSGGeogCS != -1 )
1921
 
    {
1922
 
        double padfTransform[7];
1923
 
        if( EPSGGetWGS84Transform( nEPSGGeogCS, padfTransform ) )
1924
 
        {
1925
 
            sprintf( szTOWGS84, "+towgs84=%.16g,%.16g,%.16g,%.16g,%.16g,%.16g,%.16g",
1926
 
                     padfTransform[0],
1927
 
                     padfTransform[1],
1928
 
                     padfTransform[2],
1929
 
                     padfTransform[3],
1930
 
                     padfTransform[4],
1931
 
                     padfTransform[5],
1932
 
                     padfTransform[6] );
1933
 
            pszPROJ4Datum = szTOWGS84;
 
2192
                SAFE_PROJ4_STRCAT( szTOWGS84 );
 
2193
                SAFE_PROJ4_STRCAT( " " );
 
2194
                pszPROJ4Datum = NULL;
 
2195
            }
1934
2196
        }
1935
2197
    }
1936
2198
    
1937
2199
    if( pszPROJ4Datum != NULL )
1938
2200
    {
1939
 
        strcat( szProj4, pszPROJ4Datum );
1940
 
        strcat( szProj4, " " );
 
2201
        SAFE_PROJ4_STRCAT( "+datum=" );
 
2202
        SAFE_PROJ4_STRCAT( pszPROJ4Datum );
 
2203
        SAFE_PROJ4_STRCAT( " " );
 
2204
    }
 
2205
    else // The ellipsedef may already have been appended and will now
 
2206
        // be empty, otherwise append now.
 
2207
    {
 
2208
        SAFE_PROJ4_STRCAT( szEllipseDef );
 
2209
        szEllipseDef[0] = '\0';
1941
2210
    }
1942
2211
 
1943
2212
/* -------------------------------------------------------------------- */
1953
2222
        if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
1954
2223
            nCode = atoi(GetAuthorityCode( "PRIMEM" ));
1955
2224
 
1956
 
        switch( nCode )
1957
 
        {
1958
 
          case 8902:
1959
 
            strcpy( szPMValue, "lisbon" );
1960
 
            break;
1961
 
 
1962
 
          case 8903:
1963
 
            strcpy( szPMValue, "paris" );
1964
 
            break;
1965
 
 
1966
 
          case 8904:
1967
 
            strcpy( szPMValue, "bogota" );
1968
 
            break;
1969
 
 
1970
 
          case 8905:
1971
 
            strcpy( szPMValue, "madrid" );
1972
 
            break;
1973
 
 
1974
 
          case 8906:
1975
 
            strcpy( szPMValue, "rome" );
1976
 
            break;
1977
 
 
1978
 
          case 8907:
1979
 
            strcpy( szPMValue, "bern" );
1980
 
            break;
1981
 
 
1982
 
          case 8908:
1983
 
            strcpy( szPMValue, "jakarta" );
1984
 
            break;
1985
 
 
1986
 
          case 8909:
1987
 
            strcpy( szPMValue, "ferro" );
1988
 
            break;
1989
 
 
1990
 
          case 8910:
1991
 
            strcpy( szPMValue, "brussels" );
1992
 
            break;
1993
 
 
1994
 
          case 8911:
1995
 
            strcpy( szPMValue, "stockholm" );
1996
 
            break;
1997
 
 
1998
 
          case 8912:
1999
 
            strcpy( szPMValue, "athens" );
2000
 
            break;
2001
 
 
2002
 
          case 8913:
2003
 
            strcpy( szPMValue, "oslo" );
2004
 
            break;
2005
 
 
2006
 
          default:
 
2225
        const OGRProj4PM* psProj4PM = NULL;
 
2226
        if (nCode > 0)
 
2227
            psProj4PM = OGRGetProj4PMFromCode(nCode);
 
2228
        if (psProj4PM == NULL)
 
2229
            psProj4PM = OGRGetProj4PMFromVal(dfFromGreenwich);
 
2230
 
 
2231
        if (psProj4PM != NULL)
 
2232
        {
 
2233
            strcpy( szPMValue, psProj4PM->pszProj4PMName );
 
2234
        }
 
2235
        else
 
2236
        {
2007
2237
            sprintf( szPMValue, "%.16g", dfFromGreenwich );
2008
2238
        }
2009
2239
 
2010
 
        sprintf( szProj4+strlen(szProj4), "+pm=%s ", szPMValue );
 
2240
        SAFE_PROJ4_STRCAT( "+pm=" );
 
2241
        SAFE_PROJ4_STRCAT( szPMValue );
 
2242
        SAFE_PROJ4_STRCAT( " " );
2011
2243
    }
2012
2244
    
2013
2245
/* -------------------------------------------------------------------- */
2021
2253
        
2022
2254
    if( strstr(szProj4,"longlat") != NULL )
2023
2255
        pszPROJ4Units = NULL;
2024
 
    
2025
 
    else if( dfLinearConv == 1.0 )
2026
 
        pszPROJ4Units = "m";
2027
 
 
2028
 
    else if( dfLinearConv == 1000.0 )
2029
 
        pszPROJ4Units = "km";
2030
 
    
2031
 
    else if( dfLinearConv == 0.0254 )
2032
 
        pszPROJ4Units = "in";
2033
 
    
2034
 
    else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
2035
 
             || fabs(dfLinearConv - atof(SRS_UL_FOOT_CONV)) < 0.000000001 )
2036
 
        pszPROJ4Units = "ft";
2037
 
    
2038
 
    else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
2039
 
        pszPROJ4Units = "yd";
2040
 
    
2041
 
    else if( dfLinearConv == 0.001 )
2042
 
        pszPROJ4Units = "mm";
2043
 
    
2044
 
    else if( dfLinearConv == 0.01 )
2045
 
        pszPROJ4Units = "cm";
2046
 
 
2047
 
    else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
2048
 
             || fabs(dfLinearConv - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
2049
 
        pszPROJ4Units = "us-ft";
2050
 
 
2051
 
    else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
2052
 
        pszPROJ4Units = "kmi";
2053
 
 
2054
 
    else if( EQUAL(pszLinearUnits,"Mile") 
2055
 
             || EQUAL(pszLinearUnits,"IMILE") )
2056
 
        pszPROJ4Units = "mi";
2057
 
 
2058
 
    else
 
2256
    else 
2059
2257
    {
2060
 
        sprintf( szProj4+strlen(szProj4), "+to_meter=%.16g ",
2061
 
                 dfLinearConv );
 
2258
        pszPROJ4Units = LinearToProj4( dfLinearConv, pszLinearUnits );
 
2259
 
 
2260
        if( pszPROJ4Units == NULL )
 
2261
        {
 
2262
            char szLinearConv[128];
 
2263
            sprintf( szLinearConv, "%.16g", dfLinearConv );
 
2264
            SAFE_PROJ4_STRCAT( "+to_meter=" );
 
2265
            SAFE_PROJ4_STRCAT( szLinearConv );
 
2266
            SAFE_PROJ4_STRCAT( " " );
 
2267
        }
2062
2268
    }
2063
2269
 
2064
2270
    if( pszPROJ4Units != NULL )
2065
 
        sprintf( szProj4+strlen(szProj4), "+units=%s ",
2066
 
                 pszPROJ4Units );
 
2271
    {
 
2272
        SAFE_PROJ4_STRCAT( "+units=");
 
2273
        SAFE_PROJ4_STRCAT( pszPROJ4Units );
 
2274
        SAFE_PROJ4_STRCAT( " " );
 
2275
    }
 
2276
 
 
2277
/* -------------------------------------------------------------------- */
 
2278
/*      If we have vertical datum grids, attach them to the proj.4 string.*/
 
2279
/* -------------------------------------------------------------------- */
 
2280
    const char *pszProj4Geoids = GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
 
2281
    
 
2282
    if( pszProj4Geoids != NULL )
 
2283
    {
 
2284
        SAFE_PROJ4_STRCAT( "+geoidgrids=" );
 
2285
        SAFE_PROJ4_STRCAT( pszProj4Geoids );
 
2286
        SAFE_PROJ4_STRCAT(  " " );
 
2287
    }    
 
2288
 
 
2289
/* -------------------------------------------------------------------- */
 
2290
/*      Handle vertical units, but only if we have them.                */
 
2291
/* -------------------------------------------------------------------- */
 
2292
    const OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
 
2293
    const OGR_SRSNode *poVUNITS = NULL;
 
2294
 
 
2295
    if( poVERT_CS != NULL )
 
2296
        poVUNITS = poVERT_CS->GetNode( "UNIT" );
 
2297
 
 
2298
    if( poVUNITS != NULL && poVUNITS->GetChildCount() >= 2 )
 
2299
    {
 
2300
        pszPROJ4Units = NULL;
 
2301
 
 
2302
        dfLinearConv = CPLAtof( poVUNITS->GetChild(1)->GetValue() );
 
2303
        
 
2304
        pszPROJ4Units = LinearToProj4( dfLinearConv,
 
2305
                                       poVUNITS->GetChild(0)->GetValue() );
 
2306
            
 
2307
        if( pszPROJ4Units == NULL )
 
2308
        {
 
2309
            char szLinearConv[128];
 
2310
            sprintf( szLinearConv, "%.16g", dfLinearConv );
 
2311
            SAFE_PROJ4_STRCAT( "+vto_meter=" );
 
2312
            SAFE_PROJ4_STRCAT( szLinearConv );
 
2313
            SAFE_PROJ4_STRCAT( " " );
 
2314
        }
 
2315
        else
 
2316
        {
 
2317
            SAFE_PROJ4_STRCAT( "+vunits=");
 
2318
            SAFE_PROJ4_STRCAT( pszPROJ4Units );
 
2319
            SAFE_PROJ4_STRCAT( " " );
 
2320
        }
 
2321
    }
2067
2322
 
2068
2323
/* -------------------------------------------------------------------- */
2069
2324
/*      Add the no_defs flag to ensure that no values from              */
2070
2325
/*      proj_def.dat are implicitly used with our definitions.          */
2071
2326
/* -------------------------------------------------------------------- */
2072
 
    sprintf( szProj4+strlen(szProj4), "+no_defs " );
 
2327
    SAFE_PROJ4_STRCAT( "+no_defs " );
2073
2328
    
2074
2329
    *ppszProj4 = CPLStrdup( szProj4 );
2075
2330