PageRenderTime 62ms CodeModel.GetById 35ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/Proj4/cs2cs.c

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