Statistics
| Revision:

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
}