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