svn-gvsig-desktop / trunk / libraries / libjni-proj4 / src / prog_cs2cs.c @ 7098
History | View | Annotate | Download (14.7 KB)
1 |
/******************************************************************************
|
---|---|
2 |
* $Id: cs2cs.c,v 1.8 2004/10/28 16:05:37 fwarmerdam Exp $
|
3 |
*
|
4 |
* Project: PROJ.4
|
5 |
* Purpose: Mainline program sort of like ``proj'' for converting between
|
6 |
* two coordinate systems.
|
7 |
* Author: Frank Warmerdam, warmerda@home.com
|
8 |
*
|
9 |
******************************************************************************
|
10 |
* Copyright (c) 2000, 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 |
* $Log: cs2cs.c,v $
|
32 |
* Revision 1.8 2004/10/28 16:05:37 fwarmerdam
|
33 |
* avoid using global variables from DLL
|
34 |
*
|
35 |
* Revision 1.7 2003/03/25 17:53:13 warmerda
|
36 |
* modified so that -f formats are used for Z as well
|
37 |
*
|
38 |
* Revision 1.6 2002/12/09 16:01:02 warmerda
|
39 |
* added prime meridian support
|
40 |
*
|
41 |
* Revision 1.5 2002/11/19 20:33:42 warmerda
|
42 |
* cleanup before exit to facilitate memory leak testing
|
43 |
*
|
44 |
* Revision 1.4 2001/04/05 19:32:19 warmerda
|
45 |
* use projPJ, and pj_is_latlong()
|
46 |
*
|
47 |
* Revision 1.3 2001/04/05 04:23:28 warmerda
|
48 |
* use pj_latlong_from_proj
|
49 |
*
|
50 |
* Revision 1.2 2001/02/03 18:36:55 warmerda
|
51 |
* removed some unavailable options from usage string
|
52 |
*
|
53 |
* Revision 1.1 2000/07/06 23:32:27 warmerda
|
54 |
* New
|
55 |
*
|
56 |
*/
|
57 |
|
58 |
#include <stdio.h> |
59 |
#include <stdlib.h> |
60 |
#include <ctype.h> |
61 |
#include <string.h> |
62 |
#include <math.h> |
63 |
#include "projects.h" |
64 |
#include "emess.h" |
65 |
|
66 |
#define MAX_LINE 200 |
67 |
#define MAX_PARGS 100 |
68 |
|
69 |
static projPJ fromProj, toProj;
|
70 |
|
71 |
static int |
72 |
reversein = 0, /* != 0 reverse input arguments */ |
73 |
reverseout = 0, /* != 0 reverse output arguments */ |
74 |
echoin = 0, /* echo input data to output line */ |
75 |
tag = '#'; /* beginning of line tag character */ |
76 |
static char |
77 |
*oform = (char *)0, /* output format for x-y or decimal degrees */ |
78 |
*oterr = "*\t*", /* output line for unprojectable input */ |
79 |
*usage = |
80 |
"%s\nusage: %s [ -eEfIlrstvwW [args] ] [ +opts[=arg] ]\n"
|
81 |
" [+to [+opts[=arg] [ files ]\n";
|
82 |
|
83 |
static struct FACTORS facs; |
84 |
static double (*informat)(const char *, |
85 |
char **); /* input data deformatter function */ |
86 |
|
87 |
|
88 |
/************************************************************************/
|
89 |
/* process() */
|
90 |
/* */
|
91 |
/* File processing function. */
|
92 |
/************************************************************************/
|
93 |
static void process(FILE *fid) |
94 |
|
95 |
{ |
96 |
char line[MAX_LINE+3], *s, pline[40]; |
97 |
projUV data; |
98 |
|
99 |
for (;;) {
|
100 |
double z;
|
101 |
|
102 |
++emess_dat.File_line; |
103 |
if (!(s = fgets(line, MAX_LINE, fid)))
|
104 |
break;
|
105 |
if (!strchr(s, '\n')) { /* overlong line */ |
106 |
int c;
|
107 |
(void)strcat(s, "\n"); |
108 |
/* gobble up to newline */
|
109 |
while ((c = fgetc(fid)) != EOF && c != '\n') ; |
110 |
} |
111 |
if (*s == tag) {
|
112 |
fputs(line, stdout); |
113 |
continue;
|
114 |
} |
115 |
|
116 |
if (reversein) {
|
117 |
data.v = (*informat)(s, &s); |
118 |
data.u = (*informat)(s, &s); |
119 |
} else {
|
120 |
data.u = (*informat)(s, &s); |
121 |
data.v = (*informat)(s, &s); |
122 |
} |
123 |
|
124 |
z = strtod( s, &s ); |
125 |
|
126 |
if (data.v == HUGE_VAL)
|
127 |
data.u = HUGE_VAL; |
128 |
|
129 |
if (!*s && (s > line)) --s; /* assumed we gobbled \n */ |
130 |
|
131 |
if ( echoin) {
|
132 |
int t;
|
133 |
t = *s; |
134 |
*s = '\0';
|
135 |
(void)fputs(line, stdout);
|
136 |
*s = t; |
137 |
putchar('\t');
|
138 |
} |
139 |
|
140 |
if (data.u != HUGE_VAL) {
|
141 |
if( pj_transform( fromProj, toProj, 1, 0, |
142 |
&(data.u), &(data.v), &z ) != 0 )
|
143 |
{ |
144 |
data.u = HUGE_VAL; |
145 |
data.v = HUGE_VAL; |
146 |
} |
147 |
} |
148 |
|
149 |
if (data.u == HUGE_VAL) /* error output */ |
150 |
fputs(oterr, stdout); |
151 |
|
152 |
else if (pj_is_latlong(toProj) && !oform) { /*ascii DMS output */ |
153 |
if (reverseout) {
|
154 |
fputs(rtodms(pline, data.v, 'N', 'S'), stdout); |
155 |
putchar('\t');
|
156 |
fputs(rtodms(pline, data.u, 'E', 'W'), stdout); |
157 |
} else {
|
158 |
fputs(rtodms(pline, data.u, 'E', 'W'), stdout); |
159 |
putchar('\t');
|
160 |
fputs(rtodms(pline, data.v, 'N', 'S'), stdout); |
161 |
} |
162 |
|
163 |
} else { /* x-y or decimal degree ascii output */ |
164 |
if ( pj_is_latlong(toProj) ) {
|
165 |
data.v *= RAD_TO_DEG; |
166 |
data.u *= RAD_TO_DEG; |
167 |
} |
168 |
if (reverseout) {
|
169 |
printf(oform,data.v); putchar('\t');
|
170 |
printf(oform,data.u); |
171 |
} else {
|
172 |
printf(oform,data.u); putchar('\t');
|
173 |
printf(oform,data.v); |
174 |
} |
175 |
} |
176 |
|
177 |
putchar(' ');
|
178 |
if( oform != NULL ) |
179 |
printf( oform, z ); |
180 |
else
|
181 |
printf( "%.3f", z );
|
182 |
fputs("\n", stdout );
|
183 |
} |
184 |
} |
185 |
|
186 |
/************************************************************************/
|
187 |
/* main() */
|
188 |
/************************************************************************/
|
189 |
|
190 |
int main(int argc, char **argv) |
191 |
{ |
192 |
char *arg, **eargv = argv, *from_argv[MAX_PARGS], *to_argv[MAX_PARGS],
|
193 |
**iargv = argv; |
194 |
FILE *fid; |
195 |
int from_argc=0, to_argc=0, iargc = argc, eargc = 0, c, mon = 0; |
196 |
int have_to_flag = 0, inverse = 0, i; |
197 |
|
198 |
if (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR))
|
199 |
++emess_dat.Prog_name; |
200 |
else emess_dat.Prog_name = *argv;
|
201 |
inverse = ! strncmp(emess_dat.Prog_name, "inv", 3); |
202 |
if (argc <= 1 ) { |
203 |
(void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name);
|
204 |
exit (0);
|
205 |
} |
206 |
/* process run line arguments */
|
207 |
while (--argc > 0) { /* collect run line arguments */ |
208 |
if(**++argv == '-') for(arg = *argv;;) { |
209 |
switch(*++arg) {
|
210 |
case '\0': /* position of "stdin" */ |
211 |
if (arg[-1] == '-') eargv[eargc++] = "-"; |
212 |
break;
|
213 |
case 'v': /* monitor dump of initialization */ |
214 |
mon = 1;
|
215 |
continue;
|
216 |
case 'I': /* alt. method to spec inverse */ |
217 |
inverse = 1;
|
218 |
continue;
|
219 |
case 'E': /* echo ascii input to ascii output */ |
220 |
echoin = 1;
|
221 |
continue;
|
222 |
case 't': /* set col. one char */ |
223 |
if (arg[1]) tag = *++arg; |
224 |
else emess(1,"missing -t col. 1 tag"); |
225 |
continue;
|
226 |
case 'l': /* list projections, ellipses or units */ |
227 |
if (!arg[1] || arg[1] == 'p' || arg[1] == 'P') { |
228 |
/* list projections */
|
229 |
struct PJ_LIST *lp;
|
230 |
int do_long = arg[1] == 'P', c; |
231 |
char *str;
|
232 |
|
233 |
for (lp = pj_get_list_ref() ; lp->id ; ++lp) {
|
234 |
(void)printf("%s : ", lp->id); |
235 |
if (do_long) /* possibly multiline description */ |
236 |
(void)puts(*lp->descr);
|
237 |
else { /* first line, only */ |
238 |
str = *lp->descr; |
239 |
while ((c = *str++) && c != '\n') |
240 |
putchar(c); |
241 |
putchar('\n');
|
242 |
} |
243 |
} |
244 |
} else if (arg[1] == '=') { /* list projection 'descr' */ |
245 |
struct PJ_LIST *lp;
|
246 |
|
247 |
arg += 2;
|
248 |
for (lp = pj_get_list_ref() ; lp->id ; ++lp)
|
249 |
if (!strcmp(lp->id, arg)) {
|
250 |
(void)printf("%9s : %s\n", lp->id, *lp->descr); |
251 |
break;
|
252 |
} |
253 |
} else if (arg[1] == 'e') { /* list ellipses */ |
254 |
struct PJ_ELLPS *le;
|
255 |
|
256 |
for (le = pj_get_ellps_ref(); le->id ; ++le)
|
257 |
(void)printf("%9s %-16s %-16s %s\n", |
258 |
le->id, le->major, le->ell, le->name); |
259 |
} else if (arg[1] == 'u') { /* list units */ |
260 |
struct PJ_UNITS *lu;
|
261 |
|
262 |
for (lu = pj_get_units_ref(); lu->id ; ++lu)
|
263 |
(void)printf("%12s %-20s %s\n", |
264 |
lu->id, lu->to_meter, lu->name); |
265 |
} else if (arg[1] == 'd') { /* list datums */ |
266 |
struct PJ_DATUMS *ld;
|
267 |
|
268 |
printf("__datum_id__ __ellipse___ __definition/comments______________________________\n" );
|
269 |
for (ld = pj_get_datums_ref(); ld->id ; ++ld)
|
270 |
{ |
271 |
printf("%12s %-12s %-30s\n",
|
272 |
ld->id, ld->ellipse_id, ld->defn); |
273 |
if( ld->comments != NULL && strlen(ld->comments) > 0 ) |
274 |
printf( "%25s %s\n", " ", ld->comments ); |
275 |
} |
276 |
} else if( arg[1] == 'm') { /* list prime meridians */ |
277 |
struct PJ_PRIME_MERIDIANS *lpm;
|
278 |
|
279 |
for (lpm = pj_get_prime_meridians_ref(); lpm->id ; ++lpm)
|
280 |
(void)printf("%12s %-30s\n", |
281 |
lpm->id, lpm->defn); |
282 |
} else
|
283 |
emess(1,"invalid list option: l%c",arg[1]); |
284 |
exit(0);
|
285 |
continue; /* artificial */ |
286 |
case 'e': /* error line alternative */ |
287 |
if (--argc <= 0) |
288 |
noargument: |
289 |
emess(1,"missing argument for -%c",*arg); |
290 |
oterr = *++argv; |
291 |
continue;
|
292 |
case 'W': /* specify seconds precision */ |
293 |
case 'w': /* -W for constant field width */ |
294 |
if ((c = arg[1]) != 0 && isdigit(c)) { |
295 |
set_rtodms(c - '0', *arg == 'W'); |
296 |
++arg; |
297 |
} else
|
298 |
emess(1,"-W argument missing or non-digit"); |
299 |
continue;
|
300 |
case 'f': /* alternate output format degrees or xy */ |
301 |
if (--argc <= 0) goto noargument; |
302 |
oform = *++argv; |
303 |
continue;
|
304 |
case 'r': /* reverse input */ |
305 |
reversein = 1;
|
306 |
continue;
|
307 |
case 's': /* reverse output */ |
308 |
reverseout = 1;
|
309 |
continue;
|
310 |
default:
|
311 |
emess(1, "invalid option: -%c",*arg); |
312 |
break;
|
313 |
} |
314 |
break;
|
315 |
|
316 |
} else if (strcmp(*argv,"+to") == 0 ) { |
317 |
have_to_flag = 1;
|
318 |
|
319 |
} else if (**argv == '+') { /* + argument */ |
320 |
if( have_to_flag )
|
321 |
{ |
322 |
if( to_argc < MAX_PARGS )
|
323 |
to_argv[to_argc++] = *argv + 1;
|
324 |
else
|
325 |
emess(1,"overflowed + argument table"); |
326 |
} |
327 |
else
|
328 |
{ |
329 |
if (from_argc < MAX_PARGS)
|
330 |
from_argv[from_argc++] = *argv + 1;
|
331 |
else
|
332 |
emess(1,"overflowed + argument table"); |
333 |
} |
334 |
} else /* assumed to be input file name(s) */ |
335 |
eargv[eargc++] = *argv; |
336 |
} |
337 |
if (eargc == 0 ) /* if no specific files force sysin */ |
338 |
eargv[eargc++] = "-";
|
339 |
|
340 |
/*
|
341 |
* If the user has requested inverse, then just reverse the
|
342 |
* coordinate systems.
|
343 |
*/
|
344 |
if( inverse )
|
345 |
{ |
346 |
int argcount;
|
347 |
|
348 |
for( i = 0; i < MAX_PARGS; i++ ) |
349 |
{ |
350 |
char *arg;
|
351 |
|
352 |
arg = from_argv[i]; |
353 |
from_argv[i] = to_argv[i]; |
354 |
to_argv[i] = arg; |
355 |
} |
356 |
|
357 |
argcount = from_argc; |
358 |
from_argc = to_argc; |
359 |
to_argc = argcount; |
360 |
} |
361 |
|
362 |
if (!(fromProj = pj_init(from_argc, from_argv)))
|
363 |
{ |
364 |
printf( "Using from definition: " );
|
365 |
for( i = 0; i < from_argc; i++ ) |
366 |
printf( "%s ", from_argv[i] );
|
367 |
printf( "\n" );
|
368 |
|
369 |
emess(3,"projection initialization failure\ncause: %s", |
370 |
pj_strerrno(pj_errno)); |
371 |
} |
372 |
|
373 |
if( to_argc == 0 ) |
374 |
{ |
375 |
if (!(toProj = pj_latlong_from_proj( fromProj )))
|
376 |
{ |
377 |
printf( "Using to definition: " );
|
378 |
for( i = 0; i < to_argc; i++ ) |
379 |
printf( "%s ", to_argv[i] );
|
380 |
printf( "\n" );
|
381 |
|
382 |
emess(3,"projection initialization failure\ncause: %s", |
383 |
pj_strerrno(pj_errno)); |
384 |
} |
385 |
} |
386 |
else if (!(toProj = pj_init(to_argc, to_argv))) |
387 |
{ |
388 |
printf( "Using to definition: " );
|
389 |
for( i = 0; i < to_argc; i++ ) |
390 |
printf( "%s ", to_argv[i] );
|
391 |
printf( "\n" );
|
392 |
|
393 |
emess(3,"projection initialization failure\ncause: %s", |
394 |
pj_strerrno(pj_errno)); |
395 |
} |
396 |
|
397 |
if (mon) {
|
398 |
printf( "%c ---- From Coordinate System ----\n", tag );
|
399 |
pj_pr_list(fromProj); |
400 |
printf( "%c ---- To Coordinate System ----\n", tag );
|
401 |
pj_pr_list(toProj); |
402 |
} |
403 |
|
404 |
/* set input formating control */
|
405 |
if( !fromProj->is_latlong )
|
406 |
informat = strtod; |
407 |
else {
|
408 |
informat = dmstor; |
409 |
} |
410 |
|
411 |
if( !toProj->is_latlong && !oform )
|
412 |
oform = "%.2f";
|
413 |
|
414 |
/* process input file list */
|
415 |
for ( ; eargc-- ; ++eargv) {
|
416 |
if (**eargv == '-') { |
417 |
fid = stdin; |
418 |
emess_dat.File_name = "<stdin>";
|
419 |
|
420 |
} else {
|
421 |
if ((fid = fopen(*eargv, "rt")) == NULL) { |
422 |
emess(-2, *eargv, "input file"); |
423 |
continue;
|
424 |
} |
425 |
emess_dat.File_name = *eargv; |
426 |
} |
427 |
emess_dat.File_line = 0;
|
428 |
process(fid); |
429 |
fclose(fid); |
430 |
emess_dat.File_name = 0;
|
431 |
} |
432 |
|
433 |
if( fromProj != NULL ) |
434 |
pj_free( fromProj ); |
435 |
if( toProj != NULL ) |
436 |
pj_free( toProj ); |
437 |
|
438 |
pj_deallocate_grids(); |
439 |
|
440 |
exit(0); /* normal completion */ |
441 |
} |