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