1 : /******************************************************************************
2 : * $Id: geotiff_proj4.c 1670 2009-10-09 16:29:38Z hobu $
3 : *
4 : * Project: libgeotiff
5 : * Purpose: Code to convert a normalized GeoTIFF definition into a PROJ.4
6 : * (OGDI) compatible projection string.
7 : * Author: Frank Warmerdam, warmerda@home.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ******************************************************************************
30 : */
31 :
32 : #include "cpl_serv.h"
33 : #include "geotiff.h"
34 : #include "geo_normalize.h"
35 : #include "geovalues.h"
36 :
37 : /************************************************************************/
38 : /* OSRProj4Tokenize() */
39 : /* */
40 : /* Custom tokenizing function for PROJ.4 strings. The main */
41 : /* reason we can't just use CSLTokenizeString is to handle */
42 : /* strings with a + sign in the exponents of parameter values. */
43 : /************************************************************************/
44 :
45 0 : static char **OSRProj4Tokenize( const char *pszFull )
46 :
47 : {
48 0 : char *pszStart = NULL;
49 : char *pszFullWrk;
50 : char **papszTokens;
51 : int i;
52 0 : int nTokens = 0;
53 : static const int nMaxTokens = 200;
54 :
55 0 : if( pszFull == NULL )
56 0 : return NULL;
57 :
58 0 : papszTokens = (char **) calloc(sizeof(char*),nMaxTokens);
59 :
60 0 : pszFullWrk = strdup( pszFull );
61 :
62 0 : for( i=0; pszFullWrk[i] != '\0' && nTokens != nMaxTokens-1; i++ )
63 : {
64 0 : switch( pszFullWrk[i] )
65 : {
66 : case '+':
67 0 : if( i == 0 || pszFullWrk[i-1] == '\0' )
68 : {
69 0 : if( pszStart != NULL )
70 : {
71 0 : if( strstr(pszStart,"=") != NULL )
72 : {
73 0 : papszTokens[nTokens++] = strdup(pszStart);
74 : }
75 : else
76 : {
77 : char szAsBoolean[100];
78 0 : strncpy( szAsBoolean,pszStart, sizeof(szAsBoolean)-1-4);
79 0 : szAsBoolean[sizeof(szAsBoolean)-1-4] = '\0';
80 0 : strcat( szAsBoolean,"=yes" );
81 0 : papszTokens[nTokens++] = strdup(szAsBoolean);
82 : }
83 : }
84 0 : pszStart = pszFullWrk + i + 1;
85 : }
86 0 : break;
87 :
88 : case ' ':
89 : case '\t':
90 : case '\n':
91 0 : pszFullWrk[i] = '\0';
92 : break;
93 :
94 : default:
95 : break;
96 : }
97 : }
98 :
99 0 : if( pszStart != NULL && strlen(pszStart) > 0 )
100 : {
101 0 : if (nTokens != 199)
102 0 : papszTokens[nTokens++] = strdup( pszStart );
103 : }
104 :
105 0 : free( pszFullWrk );
106 :
107 0 : return papszTokens;
108 : }
109 :
110 :
111 : /************************************************************************/
112 : /* OSR_GSV() */
113 : /************************************************************************/
114 :
115 0 : static const char *OSR_GSV( char **papszNV, const char * pszField )
116 :
117 : {
118 0 : int field_len = strlen(pszField);
119 : int i;
120 :
121 0 : if( !papszNV )
122 0 : return NULL;
123 :
124 0 : for( i = 0; papszNV[i] != NULL; i++ )
125 : {
126 0 : if( EQUALN(papszNV[i],pszField,field_len) )
127 : {
128 0 : if( papszNV[i][field_len] == '=' )
129 0 : return papszNV[i] + field_len + 1;
130 :
131 0 : if( strlen(papszNV[i]) == field_len )
132 0 : return "";
133 : }
134 : }
135 :
136 0 : return NULL;
137 : }
138 :
139 : /************************************************************************/
140 : /* OSR_GDV() */
141 : /* */
142 : /* Fetch a particular parameter out of the parameter list, or */
143 : /* the indicated default if it isn't available. This is a */
144 : /* helper function for importFromProj4(). */
145 : /************************************************************************/
146 :
147 0 : static double OSR_GDV( char **papszNV, const char * pszField,
148 : double dfDefaultValue )
149 :
150 : {
151 0 : const char *pszValue = OSR_GSV( papszNV, pszField );
152 :
153 : /* special hack to use k_0 if available. */
154 0 : if( pszValue == NULL && EQUAL(pszField,"k") )
155 0 : return OSR_GDV( papszNV, "k_0", dfDefaultValue );
156 :
157 0 : if( pszValue == NULL )
158 0 : return dfDefaultValue;
159 : else
160 0 : return atof(pszValue);
161 : }
162 :
163 : /************************************************************************/
164 : /* OSRFreeStringList() */
165 : /************************************************************************/
166 :
167 0 : static void OSRFreeStringList( char ** list )
168 :
169 : {
170 : int i;
171 :
172 0 : for( i = 0; list != NULL && list[i] != NULL; i++ )
173 0 : free( list[i] );
174 0 : free(list);
175 0 : }
176 :
177 :
178 : /************************************************************************/
179 : /* GTIFSetFromProj4() */
180 : /************************************************************************/
181 :
182 0 : int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
183 :
184 : {
185 0 : char **papszNV = OSRProj4Tokenize( proj4 );
186 0 : short nSpheroid = KvUserDefined;
187 0 : double dfSemiMajor=0.0, dfSemiMinor=0.0, dfInvFlattening=0.0;
188 0 : int nDatum = KvUserDefined;
189 0 : int nGCS = KvUserDefined;
190 : const char *value;
191 :
192 : /* -------------------------------------------------------------------- */
193 : /* Get the ellipsoid definition. */
194 : /* -------------------------------------------------------------------- */
195 0 : value = OSR_GSV( papszNV, "ellps" );
196 :
197 0 : if( value == NULL )
198 : {
199 : /* nothing */;
200 : }
201 0 : else if( EQUAL(value,"WGS84") )
202 0 : nSpheroid = Ellipse_WGS_84;
203 0 : else if( EQUAL(value,"clrk66") )
204 0 : nSpheroid = Ellipse_Clarke_1866;
205 0 : else if( EQUAL(value,"clrk80") )
206 0 : nSpheroid = Ellipse_Clarke_1880;
207 0 : else if( EQUAL(value,"GRS80") )
208 0 : nSpheroid = Ellipse_GRS_1980;
209 :
210 0 : if( nSpheroid == KvUserDefined )
211 : {
212 0 : dfSemiMajor = OSR_GDV(papszNV,"a",0.0);
213 0 : dfSemiMinor = OSR_GDV(papszNV,"b",0.0);
214 0 : dfInvFlattening = OSR_GDV(papszNV,"rf",0.0);
215 0 : if( dfSemiMinor != 0.0 && dfInvFlattening == 0.0 )
216 0 : dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0);
217 : }
218 :
219 : /* -------------------------------------------------------------------- */
220 : /* Get the GCS/Datum code. */
221 : /* -------------------------------------------------------------------- */
222 0 : value = OSR_GSV( papszNV, "datum" );
223 :
224 0 : if( value == NULL )
225 : {
226 : }
227 0 : else if( EQUAL(value,"WGS84") )
228 : {
229 0 : nGCS = GCS_WGS_84;
230 0 : nDatum = Datum_WGS84;
231 : }
232 0 : else if( EQUAL(value,"NAD83") )
233 : {
234 0 : nGCS = GCS_NAD83;
235 0 : nDatum = Datum_North_American_Datum_1983;
236 : }
237 0 : else if( EQUAL(value,"NAD27") )
238 : {
239 0 : nGCS = GCS_NAD27;
240 0 : nDatum = Datum_North_American_Datum_1927;
241 : }
242 :
243 : /* -------------------------------------------------------------------- */
244 : /* Operate on the basis of the projection name. */
245 : /* -------------------------------------------------------------------- */
246 0 : value = OSR_GSV(papszNV,"proj");
247 :
248 0 : if( value == NULL )
249 : {
250 0 : OSRFreeStringList( papszNV );
251 0 : return FALSE;
252 : }
253 :
254 0 : else if( EQUAL(value,"longlat") || EQUAL(value,"latlong") )
255 : {
256 : }
257 :
258 0 : else if( EQUAL(value,"tmerc") )
259 : {
260 0 : GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
261 : ModelTypeProjected);
262 0 : GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
263 : KvUserDefined );
264 0 : GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
265 : KvUserDefined );
266 :
267 0 : GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
268 : CT_TransverseMercator );
269 :
270 0 : GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
271 : OSR_GDV( papszNV, "lat_0", 0.0 ) );
272 :
273 0 : GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
274 : OSR_GDV( papszNV, "lon_0", 0.0 ) );
275 :
276 0 : GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
277 : OSR_GDV( papszNV, "k", 1.0 ) );
278 :
279 0 : GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
280 : OSR_GDV( papszNV, "x_0", 0.0 ) );
281 :
282 0 : GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
283 : OSR_GDV( papszNV, "y_0", 0.0 ) );
284 : }
285 :
286 0 : else if( EQUAL(value,"utm") )
287 : {
288 0 : int nZone = (int) OSR_GDV(papszNV,"zone",0);
289 0 : const char *south = OSR_GSV(papszNV,"south");
290 :
291 0 : GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
292 : ModelTypeProjected);
293 0 : GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
294 : KvUserDefined );
295 0 : GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
296 : KvUserDefined );
297 :
298 0 : GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
299 : CT_TransverseMercator );
300 :
301 0 : GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
302 : 0.0 );
303 :
304 0 : GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
305 0 : nZone * 6 - 183.0 );
306 :
307 0 : GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
308 : 0.9996 );
309 :
310 0 : GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
311 : 500000.0 );
312 :
313 0 : if( south != NULL )
314 0 : GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
315 : 10000000.0 );
316 : else
317 0 : GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
318 : 0.0 );
319 : }
320 :
321 0 : else if( EQUAL(value,"lcc")
322 : && OSR_GDV(papszNV, "lat_0", 0.0 )
323 0 : == OSR_GDV(papszNV, "lat_1", 0.0 ) )
324 : {
325 0 : GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
326 : ModelTypeProjected);
327 0 : GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
328 : KvUserDefined );
329 0 : GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
330 : KvUserDefined );
331 :
332 0 : GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
333 : CT_LambertConfConic_1SP );
334 :
335 0 : GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
336 : OSR_GDV( papszNV, "lat_0", 0.0 ) );
337 :
338 0 : GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
339 : OSR_GDV( papszNV, "lon_0", 0.0 ) );
340 :
341 0 : GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
342 : OSR_GDV( papszNV, "k", 1.0 ) );
343 :
344 0 : GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
345 : OSR_GDV( papszNV, "x_0", 0.0 ) );
346 :
347 0 : GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
348 : OSR_GDV( papszNV, "y_0", 0.0 ) );
349 : }
350 :
351 0 : else if( EQUAL(value,"lcc") )
352 : {
353 0 : GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
354 : ModelTypeProjected);
355 0 : GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
356 : KvUserDefined );
357 0 : GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
358 : KvUserDefined );
359 :
360 0 : GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
361 : CT_LambertConfConic_2SP );
362 :
363 0 : GTIFKeySet(gtif, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
364 : OSR_GDV( papszNV, "lat_0", 0.0 ) );
365 :
366 0 : GTIFKeySet(gtif, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1,
367 : OSR_GDV( papszNV, "lon_0", 0.0 ) );
368 :
369 0 : GTIFKeySet(gtif, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
370 : OSR_GDV( papszNV, "lat_1", 0.0 ) );
371 :
372 0 : GTIFKeySet(gtif, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
373 : OSR_GDV( papszNV, "lat_2", 0.0 ) );
374 :
375 0 : GTIFKeySet(gtif, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1,
376 : OSR_GDV( papszNV, "x_0", 0.0 ) );
377 :
378 0 : GTIFKeySet(gtif, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1,
379 : OSR_GDV( papszNV, "y_0", 0.0 ) );
380 : }
381 :
382 : #ifdef notdef
383 : else if( EQUAL(value,"bonne") )
384 : {
385 : SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ),
386 : OSR_GDV( papszNV, "lon_0", 0.0 ),
387 : OSR_GDV( papszNV, "x_0", 0.0 ),
388 : OSR_GDV( papszNV, "y_0", 0.0 ) );
389 : }
390 :
391 : else if( EQUAL(value,"cass") )
392 : {
393 : SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ),
394 : OSR_GDV( papszNV, "lon_0", 0.0 ),
395 : OSR_GDV( papszNV, "x_0", 0.0 ),
396 : OSR_GDV( papszNV, "y_0", 0.0 ) );
397 : }
398 :
399 : else if( EQUAL(value,"nzmg") )
400 : {
401 : SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ),
402 : OSR_GDV( papszNV, "lon_0", 173.0 ),
403 : OSR_GDV( papszNV, "x_0", 2510000.0 ),
404 : OSR_GDV( papszNV, "y_0", 6023150.0 ) );
405 : }
406 :
407 : else if( EQUAL(value,"cea") )
408 : {
409 : SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ),
410 : OSR_GDV( papszNV, "lon_0", 0.0 ),
411 : OSR_GDV( papszNV, "x_0", 0.0 ),
412 : OSR_GDV( papszNV, "y_0", 0.0 ) );
413 : }
414 :
415 : else if( EQUAL(value,"merc") /* 2SP form */
416 : && OSR_GDV(papszNV, "lat_ts", 1000.0) < 999.0 )
417 : {
418 : SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ),
419 : 0.0,
420 : OSR_GDV( papszNV, "lon_0", 0.0 ),
421 : OSR_GDV( papszNV, "x_0", 0.0 ),
422 : OSR_GDV( papszNV, "y_0", 0.0 ) );
423 : }
424 :
425 : else if( EQUAL(value,"merc") ) /* 1SP form */
426 : {
427 : SetMercator( 0.0,
428 : OSR_GDV( papszNV, "lon_0", 0.0 ),
429 : OSR_GDV( papszNV, "k", 1.0 ),
430 : OSR_GDV( papszNV, "x_0", 0.0 ),
431 : OSR_GDV( papszNV, "y_0", 0.0 ) );
432 : }
433 :
434 : else if( EQUAL(value,"stere")
435 : && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 )
436 : {
437 : SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ),
438 : OSR_GDV( papszNV, "lon_0", 0.0 ),
439 : OSR_GDV( papszNV, "k", 1.0 ),
440 : OSR_GDV( papszNV, "x_0", 0.0 ),
441 : OSR_GDV( papszNV, "y_0", 0.0 ) );
442 : }
443 :
444 : else if( EQUAL(value,"stere")
445 : && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 )
446 : {
447 : SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ),
448 : OSR_GDV( papszNV, "lon_0", 0.0 ),
449 : OSR_GDV( papszNV, "k", 1.0 ),
450 : OSR_GDV( papszNV, "x_0", 0.0 ),
451 : OSR_GDV( papszNV, "y_0", 0.0 ) );
452 : }
453 :
454 : else if( EQUALN(value,"stere",5) /* mostly sterea */
455 : && CSLFetchNameValue(papszNV,"k") != NULL )
456 : {
457 : SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ),
458 : OSR_GDV( papszNV, "lon_0", 0.0 ),
459 : OSR_GDV( papszNV, "k", 1.0 ),
460 : OSR_GDV( papszNV, "x_0", 0.0 ),
461 : OSR_GDV( papszNV, "y_0", 0.0 ) );
462 : }
463 :
464 : else if( EQUAL(value,"stere") )
465 : {
466 : SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
467 : OSR_GDV( papszNV, "lon_0", 0.0 ),
468 : 1.0,
469 : OSR_GDV( papszNV, "x_0", 0.0 ),
470 : OSR_GDV( papszNV, "y_0", 0.0 ) );
471 : }
472 :
473 : else if( EQUAL(value,"eqc") )
474 : {
475 : if( OSR_GDV( papszNV, "lat_0", 0.0 ) != OSR_GDV( papszNV, "lat_ts", 0.0 ) )
476 : SetEquirectangular2( OSR_GDV( papszNV, "lat_0", 0.0 ),
477 : OSR_GDV( papszNV, "lon_0", 0.0 )+dfFromGreenwich,
478 : OSR_GDV( papszNV, "lat_ts", 0.0 ),
479 : OSR_GDV( papszNV, "x_0", 0.0 ),
480 : OSR_GDV( papszNV, "y_0", 0.0 ) );
481 : else
482 : SetEquirectangular( OSR_GDV( papszNV, "lat_ts", 0.0 ),
483 : OSR_GDV( papszNV, "lon_0", 0.0 )+dfFromGreenwich,
484 : OSR_GDV( papszNV, "x_0", 0.0 ),
485 : OSR_GDV( papszNV, "y_0", 0.0 ) );
486 : }
487 :
488 : else if( EQUAL(value,"glabsgm") )
489 : {
490 : SetGaussLabordeReunion( OSR_GDV( papszNV, "lat_0", -21.116666667 ),
491 : OSR_GDV( papszNV, "lon_0", 55.53333333309)+dfFromGreenwich,
492 : OSR_GDV( papszNV, "k_0", 1.0 ),
493 : OSR_GDV( papszNV, "x_0", 160000.000 ),
494 : OSR_GDV( papszNV, "y_0", 50000.000 ) );
495 : }
496 :
497 : else if( EQUAL(value,"gnom") )
498 : {
499 : SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ),
500 : OSR_GDV( papszNV, "lon_0", 0.0 ),
501 : OSR_GDV( papszNV, "x_0", 0.0 ),
502 : OSR_GDV( papszNV, "y_0", 0.0 ) );
503 : }
504 :
505 : else if( EQUAL(value,"ortho") )
506 : {
507 : SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
508 : OSR_GDV( papszNV, "lon_0", 0.0 ),
509 : OSR_GDV( papszNV, "x_0", 0.0 ),
510 : OSR_GDV( papszNV, "y_0", 0.0 ) );
511 : }
512 :
513 : else if( EQUAL(value,"laea") )
514 : {
515 : SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ),
516 : OSR_GDV( papszNV, "lon_0", 0.0 ),
517 : OSR_GDV( papszNV, "x_0", 0.0 ),
518 : OSR_GDV( papszNV, "y_0", 0.0 ) );
519 : }
520 :
521 : else if( EQUAL(value,"aeqd") )
522 : {
523 : SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ),
524 : OSR_GDV( papszNV, "lon_0", 0.0 ),
525 : OSR_GDV( papszNV, "x_0", 0.0 ),
526 : OSR_GDV( papszNV, "y_0", 0.0 ) );
527 : }
528 :
529 : else if( EQUAL(value,"eqdc") )
530 : {
531 : SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ),
532 : OSR_GDV( papszNV, "lat_2", 0.0 ),
533 : OSR_GDV( papszNV, "lat_0", 0.0 ),
534 : OSR_GDV( papszNV, "lon_0", 0.0 ),
535 : OSR_GDV( papszNV, "x_0", 0.0 ),
536 : OSR_GDV( papszNV, "y_0", 0.0 ) );
537 : }
538 :
539 : else if( EQUAL(value,"mill") )
540 : {
541 : SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ),
542 : OSR_GDV( papszNV, "lon_0", 0.0 ),
543 : OSR_GDV( papszNV, "x_0", 0.0 ),
544 : OSR_GDV( papszNV, "y_0", 0.0 ) );
545 : }
546 :
547 : else if( EQUAL(value,"moll") )
548 : {
549 : SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ),
550 : OSR_GDV( papszNV, "x_0", 0.0 ),
551 : OSR_GDV( papszNV, "y_0", 0.0 ) );
552 : }
553 :
554 : else if( EQUAL(value,"eck4") )
555 : {
556 : SetEckertIV( OSR_GDV( papszNV, "lon_0", 0.0 ),
557 : OSR_GDV( papszNV, "x_0", 0.0 ),
558 : OSR_GDV( papszNV, "y_0", 0.0 ) );
559 : }
560 :
561 : else if( EQUAL(value,"eck6") )
562 : {
563 : SetEckertVI( OSR_GDV( papszNV, "lon_0", 0.0 ),
564 : OSR_GDV( papszNV, "x_0", 0.0 ),
565 : OSR_GDV( papszNV, "y_0", 0.0 ) );
566 : }
567 :
568 : else if( EQUAL(value,"poly") )
569 : {
570 : SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ),
571 : OSR_GDV( papszNV, "lon_0", 0.0 ),
572 : OSR_GDV( papszNV, "x_0", 0.0 ),
573 : OSR_GDV( papszNV, "y_0", 0.0 ) );
574 : }
575 :
576 : else if( EQUAL(value,"aea") )
577 : {
578 : SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ),
579 : OSR_GDV( papszNV, "lat_2", 0.0 ),
580 : OSR_GDV( papszNV, "lat_0", 0.0 ),
581 : OSR_GDV( papszNV, "lon_0", 0.0 ),
582 : OSR_GDV( papszNV, "x_0", 0.0 ),
583 : OSR_GDV( papszNV, "y_0", 0.0 ) );
584 : }
585 :
586 : else if( EQUAL(value,"robin") )
587 : {
588 : SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ),
589 : OSR_GDV( papszNV, "x_0", 0.0 ),
590 : OSR_GDV( papszNV, "y_0", 0.0 ) );
591 : }
592 :
593 : else if( EQUAL(value,"vandg") )
594 : {
595 : SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ),
596 : OSR_GDV( papszNV, "x_0", 0.0 ),
597 : OSR_GDV( papszNV, "y_0", 0.0 ) );
598 : }
599 :
600 : else if( EQUAL(value,"sinu") )
601 : {
602 : SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ),
603 : OSR_GDV( papszNV, "x_0", 0.0 ),
604 : OSR_GDV( papszNV, "y_0", 0.0 ) );
605 : }
606 :
607 : else if( EQUAL(value,"gall") )
608 : {
609 : SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ),
610 : OSR_GDV( papszNV, "x_0", 0.0 ),
611 : OSR_GDV( papszNV, "y_0", 0.0 ) );
612 : }
613 :
614 : else if( EQUAL(value,"goode") )
615 : {
616 : SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ),
617 : OSR_GDV( papszNV, "x_0", 0.0 ),
618 : OSR_GDV( papszNV, "y_0", 0.0 ) );
619 : }
620 :
621 : else if( EQUAL(value,"geos") )
622 : {
623 : SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ),
624 : OSR_GDV( papszNV, "h", 35785831.0 ),
625 : OSR_GDV( papszNV, "x_0", 0.0 ),
626 : OSR_GDV( papszNV, "y_0", 0.0 ) );
627 : }
628 :
629 : else if( EQUAL(value,"lcc") )
630 : {
631 : if( OSR_GDV(papszNV, "lat_0", 0.0 )
632 : == OSR_GDV(papszNV, "lat_1", 0.0 ) )
633 : {
634 : /* 1SP form */
635 : SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ),
636 : OSR_GDV( papszNV, "lon_0", 0.0 ),
637 : OSR_GDV( papszNV, "k_0", 1.0 ),
638 : OSR_GDV( papszNV, "x_0", 0.0 ),
639 : OSR_GDV( papszNV, "y_0", 0.0 ) );
640 : }
641 : else
642 : {
643 : /* 2SP form */
644 : SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ),
645 : OSR_GDV( papszNV, "lat_2", 0.0 ),
646 : OSR_GDV( papszNV, "lat_0", 0.0 ),
647 : OSR_GDV( papszNV, "lon_0", 0.0 ),
648 : OSR_GDV( papszNV, "x_0", 0.0 ),
649 : OSR_GDV( papszNV, "y_0", 0.0 ) );
650 : }
651 : }
652 :
653 : else if( EQUAL(value,"omerc") )
654 : {
655 : SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ),
656 : OSR_GDV( papszNV, "lonc", 0.0 ),
657 : OSR_GDV( papszNV, "alpha", 0.0 ),
658 : 0.0, /* ??? */
659 : OSR_GDV( papszNV, "k", 1.0 ),
660 : OSR_GDV( papszNV, "x_0", 0.0 ),
661 : OSR_GDV( papszNV, "y_0", 0.0 ) );
662 : }
663 :
664 : else if( EQUAL(value,"somerc") )
665 : {
666 : SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ),
667 : OSR_GDV( papszNV, "lon_0", 0.0 ),
668 : 90.0, 90.0,
669 : OSR_GDV( papszNV, "k", 1.0 ),
670 : OSR_GDV( papszNV, "x_0", 0.0 ),
671 : OSR_GDV( papszNV, "y_0", 0.0 ) );
672 : }
673 :
674 : else if( EQUAL(value,"krovak") )
675 : {
676 : SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ),
677 : OSR_GDV( papszNV, "lon_0", 0.0 ),
678 : OSR_GDV( papszNV, "alpha", 0.0 ),
679 : 0.0, /* pseudo_standard_parallel_1 */
680 : OSR_GDV( papszNV, "k", 1.0 ),
681 : OSR_GDV( papszNV, "x_0", 0.0 ),
682 : OSR_GDV( papszNV, "y_0", 0.0 ) );
683 : }
684 :
685 : else if( EQUAL(value, "iwm_p") )
686 : {
687 : SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ),
688 : OSR_GDV( papszNV, "lat_2", 0.0 ),
689 : OSR_GDV( papszNV, "lon_0", 0.0 ),
690 : OSR_GDV( papszNV, "x_0", 0.0 ),
691 : OSR_GDV( papszNV, "y_0", 0.0 ) );
692 : }
693 :
694 : else if( EQUAL(value, "wag1") )
695 : {
696 : SetWagner( 1, 0.0,
697 : OSR_GDV( papszNV, "x_0", 0.0 ),
698 : OSR_GDV( papszNV, "y_0", 0.0 ) );
699 : }
700 :
701 : else if( EQUAL(value, "wag2") )
702 : {
703 : SetWagner( 2, 0.0,
704 : OSR_GDV( papszNV, "x_0", 0.0 ),
705 : OSR_GDV( papszNV, "y_0", 0.0 ) );
706 : }
707 :
708 : else if( EQUAL(value, "wag3") )
709 : {
710 : SetWagner( 3,
711 : OSR_GDV( papszNV, "lat_ts", 0.0 ),
712 : OSR_GDV( papszNV, "x_0", 0.0 ),
713 : OSR_GDV( papszNV, "y_0", 0.0 ) );
714 : }
715 :
716 : else if( EQUAL(value, "wag1") )
717 : {
718 : SetWagner( 4, 0.0,
719 : OSR_GDV( papszNV, "x_0", 0.0 ),
720 : OSR_GDV( papszNV, "y_0", 0.0 ) );
721 : }
722 :
723 : else if( EQUAL(value, "wag1") )
724 : {
725 : SetWagner( 5, 0.0,
726 : OSR_GDV( papszNV, "x_0", 0.0 ),
727 : OSR_GDV( papszNV, "y_0", 0.0 ) );
728 : }
729 :
730 : else if( EQUAL(value, "wag1") )
731 : {
732 : SetWagner( 6, 0.0,
733 : OSR_GDV( papszNV, "x_0", 0.0 ),
734 : OSR_GDV( papszNV, "y_0", 0.0 ) );
735 : }
736 :
737 : else if( EQUAL(value, "wag1") )
738 : {
739 : SetWagner( 7, 0.0,
740 : OSR_GDV( papszNV, "x_0", 0.0 ),
741 : OSR_GDV( papszNV, "y_0", 0.0 ) );
742 : }
743 :
744 : else if( EQUAL(value,"tpeqd") )
745 : {
746 : SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ),
747 : OSR_GDV( papszNV, "lon_1", 0.0 ),
748 : OSR_GDV( papszNV, "lat_2", 0.0 ),
749 : OSR_GDV( papszNV, "lon_2", 0.0 ),
750 : OSR_GDV( papszNV, "x_0", 0.0 ),
751 : OSR_GDV( papszNV, "y_0", 0.0 ) );
752 : }
753 : #endif
754 : else
755 : {
756 : /* unsupported coordinate system */
757 0 : OSRFreeStringList( papszNV );
758 0 : return FALSE;
759 : }
760 :
761 : /* -------------------------------------------------------------------- */
762 : /* Write the GCS if we have it, otherwise write the datum. */
763 : /* -------------------------------------------------------------------- */
764 0 : if( nGCS != KvUserDefined )
765 : {
766 0 : GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT,
767 : 1, nGCS );
768 : }
769 : else
770 : {
771 0 : GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1,
772 : KvUserDefined );
773 0 : GTIFKeySet( gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT,
774 : 1, nDatum );
775 : }
776 :
777 : /* -------------------------------------------------------------------- */
778 : /* Write the ellipsoid if we don't know the GCS. */
779 : /* -------------------------------------------------------------------- */
780 0 : if( nGCS == KvUserDefined )
781 : {
782 0 : if( nSpheroid != KvUserDefined )
783 0 : GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
784 : nSpheroid );
785 : else
786 : {
787 0 : GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
788 : KvUserDefined );
789 0 : GTIFKeySet( gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
790 : dfSemiMajor );
791 0 : if( dfInvFlattening == 0.0 )
792 0 : GTIFKeySet( gtif, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1,
793 : dfSemiMajor );
794 : else
795 0 : GTIFKeySet( gtif, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
796 : dfInvFlattening );
797 : }
798 :
799 : }
800 :
801 : /* -------------------------------------------------------------------- */
802 : /* Linear units translation */
803 : /* -------------------------------------------------------------------- */
804 0 : value = OSR_GSV( papszNV, "units" );
805 :
806 0 : if( value == NULL )
807 : {
808 0 : value = OSR_GSV( papszNV, "to_meter" );
809 0 : if( value )
810 : {
811 0 : GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
812 : KvUserDefined );
813 0 : GTIFKeySet( gtif, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
814 : atof(value) );
815 : }
816 : }
817 0 : else if( EQUAL(value,"meter") || EQUAL(value,"m") )
818 : {
819 0 : GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
820 : Linear_Meter );
821 : }
822 0 : else if( EQUAL(value,"us-ft") )
823 : {
824 0 : GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
825 : Linear_Foot_US_Survey );
826 : }
827 0 : else if( EQUAL(value,"ft") )
828 : {
829 0 : GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
830 : Linear_Foot );
831 : }
832 :
833 :
834 0 : OSRFreeStringList( papszNV );
835 :
836 0 : return TRUE;
837 : }
838 :
839 : /************************************************************************/
840 : /* GTIFGetProj4Defn() */
841 : /************************************************************************/
842 :
843 0 : char * GTIFGetProj4Defn( GTIFDefn * psDefn )
844 :
845 : {
846 : char szProjection[512];
847 : char szUnits[64];
848 : double dfFalseEasting, dfFalseNorthing;
849 :
850 0 : if( psDefn == NULL /* || !psDefn->DefnSet */ )
851 0 : return strdup("");
852 :
853 0 : szProjection[0] = '\0';
854 :
855 : /* ==================================================================== */
856 : /* Translate the units of measure. */
857 : /* */
858 : /* Note that even with a +units, or +to_meter in effect, it is */
859 : /* still assumed that all the projection parameters are in */
860 : /* meters. */
861 : /* ==================================================================== */
862 0 : if( psDefn->UOMLength == Linear_Meter )
863 : {
864 0 : strcpy( szUnits, "+units=m " );
865 : }
866 0 : else if( psDefn->UOMLength == Linear_Foot )
867 : {
868 0 : strcpy( szUnits, "+units=ft " );
869 : }
870 0 : else if( psDefn->UOMLength == Linear_Foot_US_Survey )
871 : {
872 0 : strcpy( szUnits, "+units=us-ft " );
873 : }
874 0 : else if( psDefn->UOMLength == Linear_Foot_Indian )
875 : {
876 0 : strcpy( szUnits, "+units=ind-ft " );
877 : }
878 0 : else if( psDefn->UOMLength == Linear_Link )
879 : {
880 0 : strcpy( szUnits, "+units=link " );
881 : }
882 0 : else if( psDefn->UOMLength == Linear_Yard_Indian)
883 : {
884 0 : strcpy( szUnits, "+units=ind-yd " );
885 : }
886 0 : else if( psDefn->UOMLength == Linear_Fathom )
887 : {
888 0 : strcpy( szUnits, "+units=fath " );
889 : }
890 0 : else if( psDefn->UOMLength == Linear_Mile_International_Nautical )
891 : {
892 0 : strcpy( szUnits, "+units=kmi " );
893 : }
894 : else
895 : {
896 0 : sprintf( szUnits, "+to_meter=%.10f", psDefn->UOMLengthInMeters );
897 : }
898 :
899 : /* -------------------------------------------------------------------- */
900 : /* false easting and northing are in meters and that is what */
901 : /* PROJ.4 wants regardless of the linear units. */
902 : /* -------------------------------------------------------------------- */
903 0 : dfFalseEasting = psDefn->ProjParm[5];
904 0 : dfFalseNorthing = psDefn->ProjParm[6];
905 :
906 : /* ==================================================================== */
907 : /* Handle general projection methods. */
908 : /* ==================================================================== */
909 :
910 : /* -------------------------------------------------------------------- */
911 : /* Geographic. */
912 : /* -------------------------------------------------------------------- */
913 0 : if(psDefn->Model==ModelTypeGeographic)
914 : {
915 0 : sprintf(szProjection+strlen(szProjection),"+proj=latlong ");
916 :
917 : }
918 :
919 : /* -------------------------------------------------------------------- */
920 : /* UTM - special case override on transverse mercator so things */
921 : /* will be more meaningful to the user. */
922 : /* -------------------------------------------------------------------- */
923 0 : else if( psDefn->MapSys == MapSys_UTM_North )
924 : {
925 0 : sprintf( szProjection+strlen(szProjection),
926 : "+proj=utm +zone=%d ",
927 : psDefn->Zone );
928 : }
929 :
930 : /* -------------------------------------------------------------------- */
931 : /* Transverse Mercator */
932 : /* -------------------------------------------------------------------- */
933 0 : else if( psDefn->CTProjection == CT_TransverseMercator )
934 : {
935 0 : sprintf( szProjection+strlen(szProjection),
936 : "+proj=tmerc +lat_0=%.9f +lon_0=%.9f +k=%f +x_0=%.3f +y_0=%.3f ",
937 : psDefn->ProjParm[0],
938 : psDefn->ProjParm[1],
939 : psDefn->ProjParm[4],
940 : dfFalseEasting,
941 : dfFalseNorthing );
942 : }
943 :
944 : /* -------------------------------------------------------------------- */
945 : /* Mercator */
946 : /* -------------------------------------------------------------------- */
947 0 : else if( psDefn->CTProjection == CT_Mercator )
948 : {
949 0 : sprintf( szProjection+strlen(szProjection),
950 : "+proj=merc +lat_ts=%.9f +lon_0=%.9f +k=%f +x_0=%.3f +y_0=%.3f ",
951 : psDefn->ProjParm[0],
952 : psDefn->ProjParm[1],
953 : psDefn->ProjParm[4],
954 : dfFalseEasting,
955 : dfFalseNorthing );
956 : }
957 :
958 : /* -------------------------------------------------------------------- */
959 : /* Cassini/Soldner */
960 : /* -------------------------------------------------------------------- */
961 0 : else if( psDefn->CTProjection == CT_CassiniSoldner )
962 : {
963 0 : sprintf( szProjection+strlen(szProjection),
964 : "+proj=cass +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
965 : psDefn->ProjParm[0],
966 : psDefn->ProjParm[1],
967 : dfFalseEasting,
968 : dfFalseNorthing );
969 : }
970 :
971 : /* -------------------------------------------------------------------- */
972 : /* Oblique Stereographic - Should this really map onto */
973 : /* Stereographic? */
974 : /* -------------------------------------------------------------------- */
975 0 : else if( psDefn->CTProjection == CT_ObliqueStereographic )
976 : {
977 0 : sprintf( szProjection+strlen(szProjection),
978 : "+proj=stere +lat_0=%.9f +lon_0=%.9f +k=%f +x_0=%.3f +y_0=%.3f ",
979 : psDefn->ProjParm[0],
980 : psDefn->ProjParm[1],
981 : psDefn->ProjParm[4],
982 : dfFalseEasting,
983 : dfFalseNorthing );
984 : }
985 :
986 : /* -------------------------------------------------------------------- */
987 : /* Stereographic */
988 : /* -------------------------------------------------------------------- */
989 0 : else if( psDefn->CTProjection == CT_Stereographic )
990 : {
991 0 : sprintf( szProjection+strlen(szProjection),
992 : "+proj=stere +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
993 : psDefn->ProjParm[0],
994 : psDefn->ProjParm[1],
995 : dfFalseEasting,
996 : dfFalseNorthing );
997 : }
998 :
999 : /* -------------------------------------------------------------------- */
1000 : /* Polar Stereographic */
1001 : /* -------------------------------------------------------------------- */
1002 0 : else if( psDefn->CTProjection == CT_PolarStereographic )
1003 : {
1004 0 : if( psDefn->ProjParm[0] > 0.0 )
1005 0 : sprintf( szProjection+strlen(szProjection),
1006 : "+proj=stere +lat_0=90 +lat_ts=%.9f +lon_0=%.9f "
1007 : "+k=%.9f +x_0=%.3f +y_0=%.3f ",
1008 : psDefn->ProjParm[0],
1009 : psDefn->ProjParm[1],
1010 : psDefn->ProjParm[4],
1011 : dfFalseEasting,
1012 : dfFalseNorthing );
1013 : else
1014 0 : sprintf( szProjection+strlen(szProjection),
1015 : "+proj=stere +lat_0=-90 +lat_ts=%.9f +lon_0=%.9f "
1016 : "+k=%.9f +x_0=%.3f +y_0=%.3f ",
1017 : psDefn->ProjParm[0],
1018 : psDefn->ProjParm[1],
1019 : psDefn->ProjParm[4],
1020 : dfFalseEasting,
1021 : dfFalseNorthing );
1022 : }
1023 :
1024 : /* -------------------------------------------------------------------- */
1025 : /* Equirectangular */
1026 : /* -------------------------------------------------------------------- */
1027 0 : else if( psDefn->CTProjection == CT_Equirectangular )
1028 : {
1029 0 : sprintf( szProjection+strlen(szProjection),
1030 : "+proj=eqc +lat_0=%.9f +lon_0=%.9f +lat_ts=%.9f +x_0=%.3f +y_0=%.3f ",
1031 : psDefn->ProjParm[0],
1032 : psDefn->ProjParm[1],
1033 : psDefn->ProjParm[2],
1034 : dfFalseEasting,
1035 : dfFalseNorthing );
1036 : }
1037 :
1038 : /* -------------------------------------------------------------------- */
1039 : /* Gnomonic */
1040 : /* -------------------------------------------------------------------- */
1041 0 : else if( psDefn->CTProjection == CT_Gnomonic )
1042 : {
1043 0 : sprintf( szProjection+strlen(szProjection),
1044 : "+proj=gnom +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1045 : psDefn->ProjParm[0],
1046 : psDefn->ProjParm[1],
1047 : dfFalseEasting,
1048 : dfFalseNorthing );
1049 : }
1050 :
1051 : /* -------------------------------------------------------------------- */
1052 : /* Orthographic */
1053 : /* -------------------------------------------------------------------- */
1054 0 : else if( psDefn->CTProjection == CT_Orthographic )
1055 : {
1056 0 : sprintf( szProjection+strlen(szProjection),
1057 : "+proj=ortho +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1058 : psDefn->ProjParm[0],
1059 : psDefn->ProjParm[1],
1060 : dfFalseEasting,
1061 : dfFalseNorthing );
1062 : }
1063 :
1064 : /* -------------------------------------------------------------------- */
1065 : /* Lambert Azimuthal Equal Area */
1066 : /* -------------------------------------------------------------------- */
1067 0 : else if( psDefn->CTProjection == CT_LambertAzimEqualArea )
1068 : {
1069 0 : sprintf( szProjection+strlen(szProjection),
1070 : "+proj=laea +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1071 : psDefn->ProjParm[0],
1072 : psDefn->ProjParm[1],
1073 : dfFalseEasting,
1074 : dfFalseNorthing );
1075 : }
1076 :
1077 : /* -------------------------------------------------------------------- */
1078 : /* Azimuthal Equidistant */
1079 : /* -------------------------------------------------------------------- */
1080 0 : else if( psDefn->CTProjection == CT_AzimuthalEquidistant )
1081 : {
1082 0 : sprintf( szProjection+strlen(szProjection),
1083 : "+proj=aeqd +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1084 : psDefn->ProjParm[0],
1085 : psDefn->ProjParm[1],
1086 : dfFalseEasting,
1087 : dfFalseNorthing );
1088 : }
1089 :
1090 : /* -------------------------------------------------------------------- */
1091 : /* Miller Cylindrical */
1092 : /* -------------------------------------------------------------------- */
1093 0 : else if( psDefn->CTProjection == CT_MillerCylindrical )
1094 : {
1095 0 : sprintf( szProjection+strlen(szProjection),
1096 : "+proj=mill +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f +R_A ",
1097 : psDefn->ProjParm[0],
1098 : psDefn->ProjParm[1],
1099 : dfFalseEasting,
1100 : dfFalseNorthing );
1101 : }
1102 :
1103 : /* -------------------------------------------------------------------- */
1104 : /* Polyconic */
1105 : /* -------------------------------------------------------------------- */
1106 0 : else if( psDefn->CTProjection == CT_Polyconic )
1107 : {
1108 0 : sprintf( szProjection+strlen(szProjection),
1109 : "+proj=poly +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1110 : psDefn->ProjParm[0],
1111 : psDefn->ProjParm[1],
1112 : dfFalseEasting,
1113 : dfFalseNorthing );
1114 : }
1115 :
1116 : /* -------------------------------------------------------------------- */
1117 : /* AlbersEqualArea */
1118 : /* -------------------------------------------------------------------- */
1119 0 : else if( psDefn->CTProjection == CT_AlbersEqualArea )
1120 : {
1121 0 : sprintf( szProjection+strlen(szProjection),
1122 : "+proj=aea +lat_1=%.9f +lat_2=%.9f +lat_0=%.9f +lon_0=%.9f"
1123 : " +x_0=%.3f +y_0=%.3f ",
1124 : psDefn->ProjParm[0],
1125 : psDefn->ProjParm[1],
1126 : psDefn->ProjParm[2],
1127 : psDefn->ProjParm[3],
1128 : dfFalseEasting,
1129 : dfFalseNorthing );
1130 : }
1131 :
1132 : /* -------------------------------------------------------------------- */
1133 : /* EquidistantConic */
1134 : /* -------------------------------------------------------------------- */
1135 0 : else if( psDefn->CTProjection == CT_EquidistantConic )
1136 : {
1137 0 : sprintf( szProjection+strlen(szProjection),
1138 : "+proj=eqdc +lat_1=%.9f +lat_2=%.9f +lat_0=%.9f +lon_0=%.9f"
1139 : " +x_0=%.3f +y_0=%.3f ",
1140 : psDefn->ProjParm[0],
1141 : psDefn->ProjParm[1],
1142 : psDefn->ProjParm[2],
1143 : psDefn->ProjParm[3],
1144 : dfFalseEasting,
1145 : dfFalseNorthing );
1146 : }
1147 :
1148 : /* -------------------------------------------------------------------- */
1149 : /* Robinson */
1150 : /* -------------------------------------------------------------------- */
1151 0 : else if( psDefn->CTProjection == CT_Robinson )
1152 : {
1153 0 : sprintf( szProjection+strlen(szProjection),
1154 : "+proj=robin +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1155 : psDefn->ProjParm[1],
1156 : dfFalseEasting,
1157 : dfFalseNorthing );
1158 : }
1159 :
1160 : /* -------------------------------------------------------------------- */
1161 : /* VanDerGrinten */
1162 : /* -------------------------------------------------------------------- */
1163 0 : else if( psDefn->CTProjection == CT_VanDerGrinten )
1164 : {
1165 0 : sprintf( szProjection+strlen(szProjection),
1166 : "+proj=vandg +lon_0=%.9f +x_0=%.3f +y_0=%.3f +R_A ",
1167 : psDefn->ProjParm[1],
1168 : dfFalseEasting,
1169 : dfFalseNorthing );
1170 : }
1171 :
1172 : /* -------------------------------------------------------------------- */
1173 : /* Sinusoidal */
1174 : /* -------------------------------------------------------------------- */
1175 0 : else if( psDefn->CTProjection == CT_Sinusoidal )
1176 : {
1177 0 : sprintf( szProjection+strlen(szProjection),
1178 : "+proj=sinu +lon_0=%.9f +x_0=%.3f +y_0=%.3f ",
1179 : psDefn->ProjParm[1],
1180 : dfFalseEasting,
1181 : dfFalseNorthing );
1182 : }
1183 :
1184 : /* -------------------------------------------------------------------- */
1185 : /* LambertConfConic_2SP */
1186 : /* -------------------------------------------------------------------- */
1187 0 : else if( psDefn->CTProjection == CT_LambertConfConic_2SP )
1188 : {
1189 0 : sprintf( szProjection+strlen(szProjection),
1190 : "+proj=lcc +lat_0=%.9f +lon_0=%.9f +lat_1=%.9f +lat_2=%.9f "
1191 : " +x_0=%.3f +y_0=%.3f ",
1192 : psDefn->ProjParm[0],
1193 : psDefn->ProjParm[1],
1194 : psDefn->ProjParm[2],
1195 : psDefn->ProjParm[3],
1196 : dfFalseEasting,
1197 : dfFalseNorthing );
1198 : }
1199 :
1200 : /* -------------------------------------------------------------------- */
1201 : /* LambertConfConic_1SP */
1202 : /* -------------------------------------------------------------------- */
1203 0 : else if( psDefn->CTProjection == CT_LambertConfConic_1SP )
1204 : {
1205 0 : sprintf( szProjection+strlen(szProjection),
1206 : "+proj=lcc +lat_0=%.9f +lat_1=%.9f +lon_0=%.9f"
1207 : " +k_0=%.9f +x_0=%.3f +y_0=%.3f ",
1208 : psDefn->ProjParm[0],
1209 : psDefn->ProjParm[0],
1210 : psDefn->ProjParm[1],
1211 : psDefn->ProjParm[4],
1212 : psDefn->ProjParm[5],
1213 : psDefn->ProjParm[6] );
1214 : }
1215 :
1216 : /* -------------------------------------------------------------------- */
1217 : /* CT_CylindricalEqualArea */
1218 : /* -------------------------------------------------------------------- */
1219 0 : else if( psDefn->CTProjection == CT_CylindricalEqualArea )
1220 : {
1221 0 : sprintf( szProjection+strlen(szProjection),
1222 : "+proj=cea +lat_ts=%.9f +lon_0=%.9f "
1223 : " +x_0=%.3f +y_0=%.3f ",
1224 : psDefn->ProjParm[0],
1225 : psDefn->ProjParm[1],
1226 : psDefn->ProjParm[5],
1227 : psDefn->ProjParm[6] );
1228 : }
1229 :
1230 : /* -------------------------------------------------------------------- */
1231 : /* NewZealandMapGrid */
1232 : /* -------------------------------------------------------------------- */
1233 0 : else if( psDefn->CTProjection == CT_NewZealandMapGrid )
1234 : {
1235 0 : sprintf( szProjection+strlen(szProjection),
1236 : "+proj=nzmg +lat_0=%.9f +lon_0=%.9f"
1237 : " +x_0=%.3f +y_0=%.3f ",
1238 : psDefn->ProjParm[0],
1239 : psDefn->ProjParm[1],
1240 : psDefn->ProjParm[5],
1241 : psDefn->ProjParm[6] );
1242 : }
1243 :
1244 : /* -------------------------------------------------------------------- */
1245 : /* Transverse Mercator - south oriented. */
1246 : /* -------------------------------------------------------------------- */
1247 0 : else if( psDefn->CTProjection == CT_TransvMercator_SouthOriented )
1248 : {
1249 : /* this appears to be an unsupported formulation with PROJ.4 */
1250 : }
1251 :
1252 : /* -------------------------------------------------------------------- */
1253 : /* ObliqueMercator (Hotine) */
1254 : /* -------------------------------------------------------------------- */
1255 0 : else if( psDefn->CTProjection == CT_ObliqueMercator )
1256 : {
1257 : /* not clear how ProjParm[3] - angle from rectified to skewed grid -
1258 : should be applied ... see the +not_rot flag for PROJ.4.
1259 : Just ignoring for now. */
1260 :
1261 0 : sprintf( szProjection+strlen(szProjection),
1262 : "+proj=omerc +lat_0=%.9f +lonc=%.9f +alpha=%.9f"
1263 : " +k=%.9f +x_0=%.3f +y_0=%.3f ",
1264 : psDefn->ProjParm[0],
1265 : psDefn->ProjParm[1],
1266 : psDefn->ProjParm[2],
1267 : psDefn->ProjParm[4],
1268 : psDefn->ProjParm[5],
1269 : psDefn->ProjParm[6] );
1270 : }
1271 :
1272 : /* ==================================================================== */
1273 : /* Handle ellipsoid information. */
1274 : /* ==================================================================== */
1275 0 : if( psDefn->Ellipsoid == Ellipse_WGS_84 )
1276 0 : strcat( szProjection, "+ellps=WGS84 " );
1277 0 : else if( psDefn->Ellipsoid == Ellipse_Clarke_1866 )
1278 0 : strcat( szProjection, "+ellps=clrk66 " );
1279 0 : else if( psDefn->Ellipsoid == Ellipse_Clarke_1880 )
1280 0 : strcat( szProjection, "+ellps=clrk80 " );
1281 0 : else if( psDefn->Ellipsoid == Ellipse_GRS_1980 )
1282 0 : strcat( szProjection, "+ellps=GRS80 " );
1283 : else
1284 : {
1285 0 : if( psDefn->SemiMajor != 0.0 && psDefn->SemiMinor != 0.0 )
1286 : {
1287 0 : sprintf( szProjection+strlen(szProjection),
1288 : "+a=%.3f +b=%.3f ",
1289 : psDefn->SemiMajor,
1290 : psDefn->SemiMinor );
1291 : }
1292 : }
1293 :
1294 0 : strcat( szProjection, szUnits );
1295 :
1296 : /* If we don't have anything, reset */
1297 0 : if (strstr(szProjection,"+proj=") == NULL) { return strdup(""); }
1298 :
1299 0 : return( strdup( szProjection ) );
1300 : }
1301 :
1302 : #if !defined(HAVE_LIBPROJ) || !defined(HAVE_PROJECTS_H)
1303 :
1304 0 : int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
1305 : double *padfX, double *padfY )
1306 : {
1307 : (void) psDefn;
1308 : (void) nPoints;
1309 : (void) padfX;
1310 : (void) padfY;
1311 : #ifdef DEBUG
1312 : fprintf( stderr,
1313 : "GTIFProj4ToLatLong() - PROJ.4 support not compiled in.\n" );
1314 : #endif
1315 0 : return FALSE;
1316 : }
1317 :
1318 0 : int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
1319 : double *padfX, double *padfY )
1320 : {
1321 : (void) psDefn;
1322 : (void) nPoints;
1323 : (void) padfX;
1324 : (void) padfY;
1325 : #ifdef DEBUG
1326 : fprintf( stderr,
1327 : "GTIFProj4FromLatLong() - PROJ.4 support not compiled in.\n" );
1328 : #endif
1329 0 : return FALSE;
1330 : }
1331 : #else
1332 :
1333 : #include "projects.h"
1334 :
1335 : #ifdef USE_PROJUV
1336 : # define UV projUV
1337 : #endif
1338 :
1339 : /************************************************************************/
1340 : /* GTIFProj4FromLatLong() */
1341 : /* */
1342 : /* Convert lat/long values to projected coordinate for a */
1343 : /* particular definition. */
1344 : /************************************************************************/
1345 :
1346 : int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
1347 : double *padfX, double *padfY )
1348 :
1349 : {
1350 : char *pszProjection, **papszArgs;
1351 : PJ *psPJ;
1352 : int i;
1353 :
1354 : /* -------------------------------------------------------------------- */
1355 : /* Get a projection definition. */
1356 : /* -------------------------------------------------------------------- */
1357 : pszProjection = GTIFGetProj4Defn( psDefn );
1358 :
1359 : if( pszProjection == NULL )
1360 : return FALSE;
1361 :
1362 : /* -------------------------------------------------------------------- */
1363 : /* Parse into tokens for pj_init(), and initialize the projection. */
1364 : /* -------------------------------------------------------------------- */
1365 :
1366 : papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE );
1367 : free( pszProjection );
1368 :
1369 : psPJ = pj_init( CSLCount(papszArgs), papszArgs );
1370 :
1371 : CSLDestroy( papszArgs );
1372 :
1373 : if( psPJ == NULL )
1374 : {
1375 : return FALSE;
1376 : }
1377 :
1378 : /* -------------------------------------------------------------------- */
1379 : /* Process each of the points. */
1380 : /* -------------------------------------------------------------------- */
1381 : for( i = 0; i < nPoints; i++ )
1382 : {
1383 : UV sUV;
1384 :
1385 : sUV.u = padfX[i] * DEG_TO_RAD;
1386 : sUV.v = padfY[i] * DEG_TO_RAD;
1387 :
1388 : sUV = pj_fwd( sUV, psPJ );
1389 :
1390 : padfX[i] = sUV.u;
1391 : padfY[i] = sUV.v;
1392 : }
1393 :
1394 : pj_free( psPJ );
1395 :
1396 : return TRUE;
1397 : }
1398 :
1399 : /************************************************************************/
1400 : /* GTIFProj4ToLatLong() */
1401 : /* */
1402 : /* Convert projection coordinates to lat/long for a particular */
1403 : /* definition. */
1404 : /************************************************************************/
1405 :
1406 : int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
1407 : double *padfX, double *padfY )
1408 :
1409 : {
1410 : char *pszProjection, **papszArgs;
1411 : PJ *psPJ;
1412 : int i;
1413 :
1414 : /* -------------------------------------------------------------------- */
1415 : /* Get a projection definition. */
1416 : /* -------------------------------------------------------------------- */
1417 : pszProjection = GTIFGetProj4Defn( psDefn );
1418 :
1419 : if( pszProjection == NULL )
1420 : return FALSE;
1421 :
1422 : /* -------------------------------------------------------------------- */
1423 : /* Parse into tokens for pj_init(), and initialize the projection. */
1424 : /* -------------------------------------------------------------------- */
1425 :
1426 : papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE );
1427 : free( pszProjection );
1428 :
1429 : psPJ = pj_init( CSLCount(papszArgs), papszArgs );
1430 :
1431 : CSLDestroy( papszArgs );
1432 :
1433 : if( psPJ == NULL )
1434 : {
1435 : return FALSE;
1436 : }
1437 :
1438 : /* -------------------------------------------------------------------- */
1439 : /* Process each of the points. */
1440 : /* -------------------------------------------------------------------- */
1441 : for( i = 0; i < nPoints; i++ )
1442 : {
1443 : UV sUV;
1444 :
1445 : sUV.u = padfX[i];
1446 : sUV.v = padfY[i];
1447 :
1448 : sUV = pj_inv( sUV, psPJ );
1449 :
1450 : padfX[i] = sUV.u * RAD_TO_DEG;
1451 : padfY[i] = sUV.v * RAD_TO_DEG;
1452 : }
1453 :
1454 : pj_free( psPJ );
1455 :
1456 : return TRUE;
1457 : }
1458 :
1459 : #endif /* has projects.h and -lproj */
1460 :
|