1
/******************************************************************************
2
* $Id: cs2cs.c,v 1.4 2001/04/05 19:32:19 warmerda Exp $
5
* Purpose: Mainline program sort of like ``proj'' for converting between
6
* two coordinate systems.
7
* Author: Frank Warmerdam, warmerda@home.com
9
******************************************************************************
10
* Copyright (c) 2000, Frank Warmerdam
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:
19
* The above copyright notice and this permission notice shall be included
20
* in all copies or substantial portions of the Software.
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
******************************************************************************
32
* Revision 1.4 2001/04/05 19:32:19 warmerda
33
* use projPJ, and pj_is_latlong()
35
* Revision 1.3 2001/04/05 04:23:28 warmerda
36
* use pj_latlong_from_proj
38
* Revision 1.2 2001/02/03 18:36:55 warmerda
39
* removed some unavailable options from usage string
41
* Revision 1.1 2000/07/06 23:32:27 warmerda
57
static projPJ fromProj, toProj;
60
reversein = 0, /* != 0 reverse input arguments */
61
reverseout = 0, /* != 0 reverse output arguments */
62
echoin = 0, /* echo input data to output line */
63
tag = '#'; /* beginning of line tag character */
65
*oform = (char *)0, /* output format for x-y or decimal degrees */
66
*oterr = "*\t*", /* output line for unprojectable input */
68
"%s\nusage: %s [ -eEfIlrstvwW [args] ] [ +opts[=arg] ]\n"
69
" [+to [+opts[=arg] [ files ]\n";
71
static struct FACTORS facs;
72
static double (*informat)(const char *,
73
char **); /* input data deformatter function */
76
/************************************************************************/
79
/* File processing function. */
80
/************************************************************************/
81
static void process(FILE *fid)
84
char line[MAX_LINE+3], *s, pline[40];
90
++emess_dat.File_line;
91
if (!(s = fgets(line, MAX_LINE, fid)))
93
if (!strchr(s, '\n')) { /* overlong line */
95
(void)strcat(s, "\n");
96
/* gobble up to newline */
97
while ((c = fgetc(fid)) != EOF && c != '\n') ;
105
data.v = (*informat)(s, &s);
106
data.u = (*informat)(s, &s);
108
data.u = (*informat)(s, &s);
109
data.v = (*informat)(s, &s);
114
if (data.v == HUGE_VAL)
117
if (!*s && (s > line)) --s; /* assumed we gobbled \n */
123
(void)fputs(line, stdout);
128
if (data.u != HUGE_VAL) {
129
if( pj_transform( fromProj, toProj, 1, 0,
130
&(data.u), &(data.v), &z ) != 0 )
137
if (data.u == HUGE_VAL) /* error output */
138
fputs(oterr, stdout);
140
else if (pj_is_latlong(toProj) && !oform) { /*ascii DMS output */
142
fputs(rtodms(pline, data.v, 'N', 'S'), stdout);
144
fputs(rtodms(pline, data.u, 'E', 'W'), stdout);
146
fputs(rtodms(pline, data.u, 'E', 'W'), stdout);
148
fputs(rtodms(pline, data.v, 'N', 'S'), stdout);
151
} else { /* x-y or decimal degree ascii output */
152
if ( pj_is_latlong(toProj) ) {
153
data.v *= RAD_TO_DEG;
154
data.u *= RAD_TO_DEG;
157
printf(oform,data.v); putchar('\t');
158
printf(oform,data.u);
160
printf(oform,data.u); putchar('\t');
161
printf(oform,data.v);
167
fputs("\n", stdout );
171
/************************************************************************/
173
/************************************************************************/
175
int main(int argc, char **argv)
177
char *arg, **eargv = argv, *from_argv[MAX_PARGS], *to_argv[MAX_PARGS],
180
int from_argc=0, to_argc=0, iargc = argc, eargc = 0, c, mon = 0;
181
int have_to_flag = 0, inverse = 0, i;
183
if (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR))
184
++emess_dat.Prog_name;
185
else emess_dat.Prog_name = *argv;
186
inverse = ! strncmp(emess_dat.Prog_name, "inv", 3);
188
(void)fprintf(stderr, usage, pj_release, emess_dat.Prog_name);
191
/* process run line arguments */
192
while (--argc > 0) { /* collect run line arguments */
193
if(**++argv == '-') for(arg = *argv;;) {
195
case '\0': /* position of "stdin" */
196
if (arg[-1] == '-') eargv[eargc++] = "-";
198
case 'v': /* monitor dump of initialization */
201
case 'I': /* alt. method to spec inverse */
204
case 'E': /* echo ascii input to ascii output */
207
case 't': /* set col. one char */
208
if (arg[1]) tag = *++arg;
209
else emess(1,"missing -t col. 1 tag");
211
case 'l': /* list projections, ellipses or units */
212
if (!arg[1] || arg[1] == 'p' || arg[1] == 'P') {
213
/* list projections */
215
int do_long = arg[1] == 'P', c;
218
for (lp = pj_list ; lp->id ; ++lp) {
219
(void)printf("%s : ", lp->id);
220
if (do_long) /* possibly multiline description */
221
(void)puts(*lp->descr);
222
else { /* first line, only */
224
while ((c = *str++) && c != '\n')
229
} else if (arg[1] == '=') { /* list projection 'descr' */
233
for (lp = pj_list ; lp->id ; ++lp)
234
if (!strcmp(lp->id, arg)) {
235
(void)printf("%9s : %s\n", lp->id, *lp->descr);
238
} else if (arg[1] == 'e') { /* list ellipses */
241
for (le = pj_ellps; le->id ; ++le)
242
(void)printf("%9s %-16s %-16s %s\n",
243
le->id, le->major, le->ell, le->name);
244
} else if (arg[1] == 'u') { /* list units */
247
for (lu = pj_units; lu->id ; ++lu)
248
(void)printf("%12s %-20s %s\n",
249
lu->id, lu->to_meter, lu->name);
250
} else if (arg[1] == 'd') { /* list datums */
251
struct PJ_DATUMS *ld;
253
printf("__datum_id__ __ellipse___ __definition/comments______________________________\n" );
254
for (ld = pj_datums; ld->id ; ++ld)
256
printf("%12s %-12s %-30s\n",
257
ld->id, ld->ellipse_id, ld->defn);
258
if( ld->comments != NULL && strlen(ld->comments) > 0 )
259
printf( "%25s %s\n", " ", ld->comments );
262
emess(1,"invalid list option: l%c",arg[1]);
264
continue; /* artificial */
265
case 'e': /* error line alternative */
268
emess(1,"missing argument for -%c",*arg);
271
case 'W': /* specify seconds precision */
272
case 'w': /* -W for constant field width */
273
if ((c = arg[1]) != 0 && isdigit(c)) {
274
set_rtodms(c - '0', *arg == 'W');
277
emess(1,"-W argument missing or non-digit");
279
case 'f': /* alternate output format degrees or xy */
280
if (--argc <= 0) goto noargument;
283
case 'r': /* reverse input */
286
case 's': /* reverse output */
290
emess(1, "invalid option: -%c",*arg);
295
} else if (strcmp(*argv,"+to") == 0 ) {
298
} else if (**argv == '+') { /* + argument */
301
if( to_argc < MAX_PARGS )
302
to_argv[to_argc++] = *argv + 1;
304
emess(1,"overflowed + argument table");
308
if (from_argc < MAX_PARGS)
309
from_argv[from_argc++] = *argv + 1;
311
emess(1,"overflowed + argument table");
313
} else /* assumed to be input file name(s) */
314
eargv[eargc++] = *argv;
316
if (eargc == 0 ) /* if no specific files force sysin */
317
eargv[eargc++] = "-";
320
* If the user has requested inverse, then just reverse the
321
* coordinate systems.
327
for( i = 0; i < MAX_PARGS; i++ )
332
from_argv[i] = to_argv[i];
336
argcount = from_argc;
341
if (!(fromProj = pj_init(from_argc, from_argv)))
343
printf( "Using from definition: " );
344
for( i = 0; i < from_argc; i++ )
345
printf( "%s ", from_argv[i] );
348
emess(3,"projection initialization failure\ncause: %s",
349
pj_strerrno(pj_errno));
354
if (!(toProj = pj_latlong_from_proj( fromProj )))
356
printf( "Using to definition: " );
357
for( i = 0; i < to_argc; i++ )
358
printf( "%s ", to_argv[i] );
361
emess(3,"projection initialization failure\ncause: %s",
362
pj_strerrno(pj_errno));
365
else if (!(toProj = pj_init(to_argc, to_argv)))
367
printf( "Using to definition: " );
368
for( i = 0; i < to_argc; i++ )
369
printf( "%s ", to_argv[i] );
372
emess(3,"projection initialization failure\ncause: %s",
373
pj_strerrno(pj_errno));
377
printf( "%c ---- From Coordinate System ----\n", tag );
378
pj_pr_list(fromProj);
379
printf( "%c ---- To Coordinate System ----\n", tag );
383
/* set input formating control */
384
if( !fromProj->is_latlong )
390
if( !toProj->is_latlong && !oform )
393
/* process input file list */
394
for ( ; eargc-- ; ++eargv) {
395
if (**eargv == '-') {
397
emess_dat.File_name = "<stdin>";
400
if ((fid = fopen(*eargv, "rt")) == NULL) {
401
emess(-2, *eargv, "input file");
404
emess_dat.File_name = *eargv;
406
emess_dat.File_line = 0;
409
emess_dat.File_name = 0;
411
exit(0); /* normal completion */