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