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