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