1 : /******************************************************************************
2 : * $Id: gxf_proj4.c 25164 2012-10-20 13:42:32Z rouault $
3 : *
4 : * Project: GXF Reader
5 : * Purpose: Handle GXF to PROJ.4 projection transformation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, Global Geomatics
10 : * Copyright (c) 1998, 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 : #include "gxfopen.h"
32 :
33 : CPL_CVSID("$Id: gxf_proj4.c 25164 2012-10-20 13:42:32Z rouault $");
34 :
35 : /************************************************************************/
36 : /* GXFGetMapProjectionAsPROJ4() */
37 : /************************************************************************/
38 :
39 : /**
40 : * Return the GXF Projection in PROJ.4 format.
41 : *
42 : * The returned string becomes owned by the caller, and should be freed
43 : * with CPLFree() or VSIFree(). The return value will be "unknown" if
44 : * no projection information is passed.
45 : *
46 : * The mapping of GXF projections to PROJ.4 format is not complete. Please
47 : * see the gxf_proj4.c code to better understand limitations of this
48 : * translation. Noteable PROJ.4 knows little about datums.
49 : *
50 : * For example, the following GXF definitions:
51 : * <pre>
52 : * #UNIT_LENGTH
53 : * m,1
54 : * #MAP_PROJECTION
55 : * "NAD83 / UTM zone 19N"
56 : * "GRS 1980",6378137,0.081819191,0
57 : * "Transverse Mercator",0,-69,0.9996,500000,0
58 : * </pre>
59 : *
60 : * Would translate to:
61 : * <pre>
62 : * +proj=tmerc +lat_0=0 +lon_0=-69 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80
63 : * </pre>
64 : *
65 : * @param hGXF handle to GXF file, as returned by GXFOpen().
66 : *
67 : * @return string containing PROJ.4 projection.
68 : */
69 :
70 0 : char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
71 :
72 : {
73 0 : GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
74 0 : char **papszMethods = NULL;
75 : char szPROJ4[512];
76 :
77 : /* -------------------------------------------------------------------- */
78 : /* If there was nothing in the file return "unknown". */
79 : /* -------------------------------------------------------------------- */
80 0 : if( CSLCount(psGXF->papszMapProjection) < 2 )
81 0 : return( CPLStrdup( "unknown" ) );
82 :
83 0 : szPROJ4[0] = '\0';
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Parse the third line, looking for known projection methods. */
87 : /* -------------------------------------------------------------------- */
88 0 : if( psGXF->papszMapProjection[2] != NULL )
89 : {
90 0 : if( strlen(psGXF->papszMapProjection[2]) > 80 )
91 0 : return( CPLStrdup( "" ) );
92 0 : papszMethods = CSLTokenizeStringComplex(psGXF->papszMapProjection[2],
93 : ",", TRUE, TRUE );
94 : }
95 :
96 : #ifdef DBMALLOC
97 : malloc_chain_check(1);
98 : #endif
99 :
100 0 : if( papszMethods == NULL
101 0 : || papszMethods[0] == NULL
102 0 : || EQUAL(papszMethods[0],"Geographic") )
103 : {
104 0 : strcat( szPROJ4, "+proj=longlat" );
105 : }
106 :
107 : #ifdef notdef
108 : else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (1SP)")
109 : && CSLCount(papszMethods) > 5 )
110 : {
111 : /* notdef: It isn't clear that this 1SP + scale method is even
112 : supported by PROJ.4
113 : Later note: It is not. */
114 :
115 : strcat( szPROJ4, "+proj=lcc" );
116 :
117 : strcat( szPROJ4, " +lat_0=" );
118 : strcat( szPROJ4, papszMethods[1] );
119 :
120 : strcat( szPROJ4, " +lon_0=" );
121 : strcat( szPROJ4, papszMethods[2] );
122 :
123 : strcat( szPROJ4, " +k=" );
124 : strcat( szPROJ4, papszMethods[3] );
125 :
126 : strcat( szPROJ4, " +x_0=" );
127 : strcat( szPROJ4, papszMethods[4] );
128 :
129 : strcat( szPROJ4, " +y_0=" );
130 : strcat( szPROJ4, papszMethods[5] );
131 : }
132 : #endif
133 0 : else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (2SP)")
134 0 : || EQUAL(papszMethods[0],"Lambert Conformal (2SP Belgium)") )
135 : {
136 : /* notdef: Note we are apparently losing whatever makes the
137 : Belgium variant different than normal LCC, but hopefully
138 : they are close! */
139 :
140 0 : strcat( szPROJ4, "+proj=lcc" );
141 :
142 0 : if( CSLCount(papszMethods) > 1 )
143 : {
144 0 : strcat( szPROJ4, " +lat_1=" );
145 0 : strcat( szPROJ4, papszMethods[1] );
146 : }
147 :
148 0 : if( CSLCount(papszMethods) > 2 )
149 : {
150 0 : strcat( szPROJ4, " +lat_2=" );
151 0 : strcat( szPROJ4, papszMethods[2] );
152 : }
153 :
154 0 : if( CSLCount(papszMethods) > 3 )
155 : {
156 0 : strcat( szPROJ4, " +lat_0=" );
157 0 : strcat( szPROJ4, papszMethods[3] );
158 : }
159 :
160 0 : if( CSLCount(papszMethods) > 4 )
161 : {
162 0 : strcat( szPROJ4, " +lon_0=" );
163 0 : strcat( szPROJ4, papszMethods[4] );
164 : }
165 :
166 0 : if( CSLCount(papszMethods) > 5 )
167 : {
168 0 : strcat( szPROJ4, " +x_0=" );
169 0 : strcat( szPROJ4, papszMethods[5] );
170 : }
171 :
172 0 : if( CSLCount(papszMethods) > 6 )
173 : {
174 0 : strcat( szPROJ4, " +y_0=" );
175 0 : strcat( szPROJ4, papszMethods[6] );
176 : }
177 : }
178 :
179 0 : else if( EQUAL(papszMethods[0],"Mercator (1SP)")
180 0 : && CSLCount(papszMethods) > 5 )
181 : {
182 : /* notdef: it isn't clear that +proj=merc support a scale of other
183 : than 1.0 in PROJ.4 */
184 :
185 0 : strcat( szPROJ4, "+proj=merc" );
186 :
187 0 : strcat( szPROJ4, " +lat_ts=" );
188 0 : strcat( szPROJ4, papszMethods[1] );
189 :
190 0 : strcat( szPROJ4, " +lon_0=" );
191 0 : strcat( szPROJ4, papszMethods[2] );
192 :
193 0 : strcat( szPROJ4, " +k=" );
194 0 : strcat( szPROJ4, papszMethods[3] );
195 :
196 0 : strcat( szPROJ4, " +x_0=" );
197 0 : strcat( szPROJ4, papszMethods[4] );
198 :
199 0 : strcat( szPROJ4, " +y_0=" );
200 0 : strcat( szPROJ4, papszMethods[5] );
201 : }
202 :
203 0 : else if( EQUAL(papszMethods[0],"Mercator (2SP)")
204 0 : && CSLCount(papszMethods) > 4 )
205 : {
206 : /* notdef: it isn't clear that +proj=merc support a scale of other
207 : than 1.0 in PROJ.4 */
208 :
209 0 : strcat( szPROJ4, "+proj=merc" );
210 :
211 0 : strcat( szPROJ4, " +lat_ts=" );
212 0 : strcat( szPROJ4, papszMethods[1] );
213 :
214 0 : strcat( szPROJ4, " +lon_0=" );
215 0 : strcat( szPROJ4, papszMethods[2] );
216 :
217 0 : strcat( szPROJ4, " +x_0=" );
218 0 : strcat( szPROJ4, papszMethods[3] );
219 :
220 0 : strcat( szPROJ4, " +y_0=" );
221 0 : strcat( szPROJ4, papszMethods[4] );
222 : }
223 :
224 0 : else if( EQUAL(papszMethods[0],"Hotine Oblique Mercator")
225 0 : && CSLCount(papszMethods) > 7 )
226 : {
227 : /* Note that only the second means of specifying omerc is supported
228 : by this code in GXF. */
229 0 : strcat( szPROJ4, "+proj=omerc" );
230 :
231 0 : strcat( szPROJ4, " +lat_0=" );
232 0 : strcat( szPROJ4, papszMethods[1] );
233 :
234 0 : strcat( szPROJ4, " +lonc=" );
235 0 : strcat( szPROJ4, papszMethods[2] );
236 :
237 0 : strcat( szPROJ4, " +alpha=" );
238 0 : strcat( szPROJ4, papszMethods[3] );
239 :
240 0 : if( atof(papszMethods[4]) < 0.00001 )
241 : {
242 0 : strcat( szPROJ4, " +not_rot" );
243 : }
244 : else
245 : {
246 : #ifdef notdef
247 : if( atof(papszMethods[4]) + atof(papszMethods[3]) < 0.00001 )
248 : /* ok */;
249 : else
250 : /* notdef: no way to specify arbitrary angles! */;
251 : #endif
252 : }
253 :
254 0 : strcat( szPROJ4, " +k=" );
255 0 : strcat( szPROJ4, papszMethods[5] );
256 :
257 0 : strcat( szPROJ4, " +x_0=" );
258 0 : strcat( szPROJ4, papszMethods[6] );
259 :
260 0 : strcat( szPROJ4, " +y_0=" );
261 0 : strcat( szPROJ4, papszMethods[7] );
262 : }
263 :
264 0 : else if( EQUAL(papszMethods[0],"Laborde Oblique Mercator")
265 0 : && CSLCount(papszMethods) > 6 )
266 : {
267 0 : strcat( szPROJ4, "+proj=labrd" );
268 :
269 0 : strcat( szPROJ4, " +lat_0=" );
270 0 : strcat( szPROJ4, papszMethods[1] );
271 :
272 0 : strcat( szPROJ4, " +lon_0=" );
273 0 : strcat( szPROJ4, papszMethods[2] );
274 :
275 0 : strcat( szPROJ4, " +azi=" );
276 0 : strcat( szPROJ4, papszMethods[3] );
277 :
278 0 : strcat( szPROJ4, " +k=" );
279 0 : strcat( szPROJ4, papszMethods[4] );
280 :
281 0 : strcat( szPROJ4, " +x_0=" );
282 0 : strcat( szPROJ4, papszMethods[5] );
283 :
284 0 : strcat( szPROJ4, " +y_0=" );
285 0 : strcat( szPROJ4, papszMethods[6] );
286 : }
287 :
288 0 : else if( EQUAL(papszMethods[0],"New Zealand Map Grid")
289 0 : && CSLCount(papszMethods) > 4 )
290 : {
291 0 : strcat( szPROJ4, "+proj=nzmg" );
292 :
293 0 : strcat( szPROJ4, " +lat_0=" );
294 0 : strcat( szPROJ4, papszMethods[1] );
295 :
296 0 : strcat( szPROJ4, " +lon_0=" );
297 0 : strcat( szPROJ4, papszMethods[2] );
298 :
299 0 : strcat( szPROJ4, " +x_0=" );
300 0 : strcat( szPROJ4, papszMethods[3] );
301 :
302 0 : strcat( szPROJ4, " +y_0=" );
303 0 : strcat( szPROJ4, papszMethods[4] );
304 : }
305 :
306 0 : else if( EQUAL(papszMethods[0],"New Zealand Map Grid")
307 0 : && CSLCount(papszMethods) > 4 )
308 : {
309 0 : strcat( szPROJ4, "+proj=nzmg" );
310 :
311 0 : strcat( szPROJ4, " +lat_0=" );
312 0 : strcat( szPROJ4, papszMethods[1] );
313 :
314 0 : strcat( szPROJ4, " +lon_0=" );
315 0 : strcat( szPROJ4, papszMethods[2] );
316 :
317 0 : strcat( szPROJ4, " +x_0=" );
318 0 : strcat( szPROJ4, papszMethods[3] );
319 :
320 0 : strcat( szPROJ4, " +y_0=" );
321 0 : strcat( szPROJ4, papszMethods[4] );
322 : }
323 :
324 0 : else if( EQUAL(papszMethods[0],"Oblique Stereographic")
325 0 : && CSLCount(papszMethods) > 5 )
326 : {
327 : /* there is an option to produce +lat_ts, which we ignore */
328 :
329 0 : strcat( szPROJ4, "+proj=stere" );
330 :
331 0 : strcat( szPROJ4, " +lat_0=45" );
332 :
333 0 : strcat( szPROJ4, " +lat_ts=" );
334 0 : strcat( szPROJ4, papszMethods[1] );
335 :
336 0 : strcat( szPROJ4, " +lon_0=" );
337 0 : strcat( szPROJ4, papszMethods[2] );
338 :
339 0 : strcat( szPROJ4, " +k=" );
340 0 : strcat( szPROJ4, papszMethods[3] );
341 :
342 0 : strcat( szPROJ4, " +x_0=" );
343 0 : strcat( szPROJ4, papszMethods[4] );
344 :
345 0 : strcat( szPROJ4, " +y_0=" );
346 0 : strcat( szPROJ4, papszMethods[5] );
347 : }
348 :
349 0 : else if( EQUAL(papszMethods[0],"Polar Stereographic")
350 0 : && CSLCount(papszMethods) > 5 )
351 : {
352 : /* there is an option to produce +lat_ts, which we ignore */
353 :
354 0 : strcat( szPROJ4, "+proj=stere" );
355 :
356 0 : strcat( szPROJ4, " +lat_0=90" );
357 :
358 0 : strcat( szPROJ4, " +lat_ts=" );
359 0 : strcat( szPROJ4, papszMethods[1] );
360 :
361 0 : strcat( szPROJ4, " +lon_0=" );
362 0 : strcat( szPROJ4, papszMethods[2] );
363 :
364 0 : strcat( szPROJ4, " +k=" );
365 0 : strcat( szPROJ4, papszMethods[3] );
366 :
367 0 : strcat( szPROJ4, " +x_0=" );
368 0 : strcat( szPROJ4, papszMethods[4] );
369 :
370 0 : strcat( szPROJ4, " +y_0=" );
371 0 : strcat( szPROJ4, papszMethods[5] );
372 : }
373 :
374 0 : else if( EQUAL(papszMethods[0],"Swiss Oblique Cylindrical")
375 0 : && CSLCount(papszMethods) > 4 )
376 : {
377 : /* notdef: geotiff's geo_ctrans.inc says this is the same as
378 : ObliqueMercator_Rosenmund, which GG's geotiff support just
379 : maps directly to +proj=omerc, though I find that questionable. */
380 :
381 0 : strcat( szPROJ4, "+proj=omerc" );
382 :
383 0 : strcat( szPROJ4, " +lat_0=" );
384 0 : strcat( szPROJ4, papszMethods[1] );
385 :
386 0 : strcat( szPROJ4, " +lonc=" );
387 0 : strcat( szPROJ4, papszMethods[2] );
388 :
389 0 : strcat( szPROJ4, " +x_0=" );
390 0 : strcat( szPROJ4, papszMethods[3] );
391 :
392 0 : strcat( szPROJ4, " +y_0=" );
393 0 : strcat( szPROJ4, papszMethods[4] );
394 : }
395 :
396 0 : else if( EQUAL(papszMethods[0],"Transverse Mercator")
397 0 : && CSLCount(papszMethods) > 5 )
398 : {
399 : /* notdef: geotiff's geo_ctrans.inc says this is the same as
400 : ObliqueMercator_Rosenmund, which GG's geotiff support just
401 : maps directly to +proj=omerc, though I find that questionable. */
402 :
403 0 : strcat( szPROJ4, "+proj=tmerc" );
404 :
405 0 : strcat( szPROJ4, " +lat_0=" );
406 0 : strcat( szPROJ4, papszMethods[1] );
407 :
408 0 : strcat( szPROJ4, " +lon_0=" );
409 0 : strcat( szPROJ4, papszMethods[2] );
410 :
411 0 : strcat( szPROJ4, " +k=" );
412 0 : strcat( szPROJ4, papszMethods[3] );
413 :
414 0 : strcat( szPROJ4, " +x_0=" );
415 0 : strcat( szPROJ4, papszMethods[4] );
416 :
417 0 : strcat( szPROJ4, " +y_0=" );
418 0 : strcat( szPROJ4, papszMethods[5] );
419 : }
420 :
421 0 : else if( EQUAL(papszMethods[0],"Transverse Mercator (South Oriented)")
422 0 : && CSLCount(papszMethods) > 5 )
423 : {
424 : /* notdef: I don't know how south oriented is different from
425 : normal, and I don't find any mention of it in Geotiff;s geo_ctrans.
426 : Translating as tmerc, but that is presumably wrong. */
427 :
428 0 : strcat( szPROJ4, "+proj=tmerc" );
429 :
430 0 : strcat( szPROJ4, " +lat_0=" );
431 0 : strcat( szPROJ4, papszMethods[1] );
432 :
433 0 : strcat( szPROJ4, " +lon_0=" );
434 0 : strcat( szPROJ4, papszMethods[2] );
435 :
436 0 : strcat( szPROJ4, " +k=" );
437 0 : strcat( szPROJ4, papszMethods[3] );
438 :
439 0 : strcat( szPROJ4, " +x_0=" );
440 0 : strcat( szPROJ4, papszMethods[4] );
441 :
442 0 : strcat( szPROJ4, " +y_0=" );
443 0 : strcat( szPROJ4, papszMethods[5] );
444 : }
445 :
446 0 : else if( EQUAL(papszMethods[0],"*Equidistant Conic")
447 0 : && CSLCount(papszMethods) > 6 )
448 : {
449 0 : strcat( szPROJ4, "+proj=eqdc" );
450 :
451 0 : strcat( szPROJ4, " +lat_1=" );
452 0 : strcat( szPROJ4, papszMethods[1] );
453 :
454 0 : strcat( szPROJ4, " +lat_2=" );
455 0 : strcat( szPROJ4, papszMethods[2] );
456 :
457 0 : strcat( szPROJ4, " +lat_0=" );
458 0 : strcat( szPROJ4, papszMethods[3] );
459 :
460 0 : strcat( szPROJ4, " +lon_0=" );
461 0 : strcat( szPROJ4, papszMethods[4] );
462 :
463 0 : strcat( szPROJ4, " +x_0=" );
464 0 : strcat( szPROJ4, papszMethods[5] );
465 :
466 0 : strcat( szPROJ4, " +y_0=" );
467 0 : strcat( szPROJ4, papszMethods[6] );
468 : }
469 :
470 0 : else if( EQUAL(papszMethods[0],"*Polyconic")
471 0 : && CSLCount(papszMethods) > 5 )
472 : {
473 0 : strcat( szPROJ4, "+proj=poly" );
474 :
475 0 : strcat( szPROJ4, " +lat_0=" );
476 0 : strcat( szPROJ4, papszMethods[1] );
477 :
478 0 : strcat( szPROJ4, " +lon_0=" );
479 0 : strcat( szPROJ4, papszMethods[2] );
480 :
481 : #ifdef notdef
482 : /*not supported by PROJ.4 */
483 : strcat( szPROJ4, " +k=" );
484 : strcat( szPROJ4, papszMethods[3] );
485 : #endif
486 0 : strcat( szPROJ4, " +x_0=" );
487 0 : strcat( szPROJ4, papszMethods[4] );
488 :
489 0 : strcat( szPROJ4, " +y_0=" );
490 0 : strcat( szPROJ4, papszMethods[5] );
491 : }
492 :
493 : else
494 : {
495 0 : strcat( szPROJ4, "unknown" );
496 : }
497 :
498 0 : CSLDestroy( papszMethods );
499 :
500 : /* -------------------------------------------------------------------- */
501 : /* Now get the ellipsoid parameters. For a bunch of common */
502 : /* ones we preserve the name. For the rest we just carry over */
503 : /* the parameters. */
504 : /* -------------------------------------------------------------------- */
505 0 : if( CSLCount(psGXF->papszMapProjection) > 1 )
506 : {
507 : char **papszTokens;
508 :
509 0 : if( strlen(psGXF->papszMapProjection[1]) > 80 )
510 0 : return CPLStrdup("");
511 :
512 0 : papszTokens = CSLTokenizeStringComplex(psGXF->papszMapProjection[1],
513 : ",", TRUE, TRUE );
514 :
515 :
516 0 : if( EQUAL(papszTokens[0],"WGS 84") )
517 0 : strcat( szPROJ4, " +ellps=WGS84" );
518 0 : else if( EQUAL(papszTokens[0],"*WGS 72") )
519 0 : strcat( szPROJ4, " +ellps=WGS72" );
520 0 : else if( EQUAL(papszTokens[0],"*WGS 66") )
521 0 : strcat( szPROJ4, " +ellps=WGS66" );
522 0 : else if( EQUAL(papszTokens[0],"*WGS 60") )
523 0 : strcat( szPROJ4, " +ellps=WGS60" );
524 0 : else if( EQUAL(papszTokens[0],"Clarke 1866") )
525 0 : strcat( szPROJ4, " +ellps=clrk66" );
526 0 : else if( EQUAL(papszTokens[0],"Clarke 1880") )
527 0 : strcat( szPROJ4, " +ellps=clrk80" );
528 0 : else if( EQUAL(papszTokens[0],"GRS 1980") )
529 0 : strcat( szPROJ4, " +ellps=GRS80" );
530 0 : else if( CSLCount( papszTokens ) > 2 )
531 : {
532 0 : sprintf( szPROJ4+strlen(szPROJ4),
533 : " +a=%s +e=%s",
534 0 : papszTokens[1], papszTokens[2] );
535 : }
536 :
537 0 : CSLDestroy(papszTokens);
538 : }
539 :
540 : /* -------------------------------------------------------------------- */
541 : /* Extract the units specification. */
542 : /* -------------------------------------------------------------------- */
543 0 : if( psGXF->pszUnitName != NULL )
544 : {
545 0 : if( EQUAL(psGXF->pszUnitName,"ft") )
546 : {
547 0 : strcat( szPROJ4, " +units=ft" );
548 : }
549 0 : else if( EQUAL(psGXF->pszUnitName,"ftUS") )
550 : {
551 0 : strcat( szPROJ4, " +units=us-ft" );
552 : }
553 0 : else if( EQUAL(psGXF->pszUnitName,"km") )
554 : {
555 0 : strcat( szPROJ4, " +units=km" );
556 : }
557 0 : else if( EQUAL(psGXF->pszUnitName,"mm") )
558 : {
559 0 : strcat( szPROJ4, " +units=mm" );
560 : }
561 0 : else if( EQUAL(psGXF->pszUnitName,"in") )
562 : {
563 0 : strcat( szPROJ4, " +units=in" );
564 : }
565 0 : else if( EQUAL(psGXF->pszUnitName,"ftInd") )
566 : {
567 0 : strcat( szPROJ4, " +units=ind-ft" );
568 : }
569 0 : else if( EQUAL(psGXF->pszUnitName,"lk") )
570 : {
571 0 : strcat( szPROJ4, " +units=link" );
572 : }
573 : }
574 :
575 0 : return( CPLStrdup( szPROJ4 ) );
576 : }
577 :
578 :
579 : /************************************************************************/
580 : /* GXFGetPROJ4Position() */
581 : /* */
582 : /* Get the same information as GXFGetPosition(), but adjust */
583 : /* to units to meters if we don't ``know'' the indicated */
584 : /* units. */
585 : /************************************************************************/
586 :
587 0 : CPLErr GXFGetPROJ4Position( GXFHandle hGXF,
588 : double * pdfXOrigin, double * pdfYOrigin,
589 : double * pdfXPixelSize, double * pdfYPixelSize,
590 : double * pdfRotation )
591 :
592 : {
593 0 : GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
594 : char *pszProj;
595 :
596 : /* -------------------------------------------------------------------- */
597 : /* Get the raw position. */
598 : /* -------------------------------------------------------------------- */
599 0 : if( GXFGetPosition( hGXF,
600 : pdfXOrigin, pdfYOrigin,
601 : pdfXPixelSize, pdfYPixelSize,
602 : pdfRotation ) == CE_Failure )
603 0 : return( CE_Failure );
604 :
605 : /* -------------------------------------------------------------------- */
606 : /* Do we know the units in PROJ.4? Get the PROJ.4 string, and */
607 : /* check for a +units definition. */
608 : /* -------------------------------------------------------------------- */
609 0 : pszProj = GXFGetMapProjectionAsPROJ4( hGXF );
610 0 : if( strstr(pszProj,"+unit") == NULL && psGXF->pszUnitName != NULL )
611 : {
612 0 : if( pdfXOrigin != NULL )
613 0 : *pdfXOrigin *= psGXF->dfUnitToMeter;
614 0 : if( pdfYOrigin != NULL )
615 0 : *pdfYOrigin *= psGXF->dfUnitToMeter;
616 0 : if( pdfXPixelSize != NULL )
617 0 : *pdfXPixelSize *= psGXF->dfUnitToMeter;
618 0 : if( pdfYPixelSize != NULL )
619 0 : *pdfYPixelSize *= psGXF->dfUnitToMeter;
620 : }
621 0 : CPLFree( pszProj );
622 :
623 0 : return( CE_None );
624 : }
|