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