home *** CD-ROM | disk | FTP | other *** search
- /*
- wmap2ps
-
- Description: converts files from the WORLDMAP package
- (MP1 format) by John B. Allison to PostScript
-
- The program expects input from stdin in WORLDMAP format
- as described below and writes a corresponding PostScript
- file to stdout.
-
- Written by Patsch in September 1992 (I needed the map of Tassie...)
-
- This program is in the Public Domain, as
- long as the README file is kept intact.
-
- =====================================================================
-
- Usage :
-
- wmap2ps [ -u unit ] %% one from { cm, in, pt }
- [ -o x y ] %% lower left corner of image
- [ -w width ] %% desired target width/height
- [ -h height ] %% using the current unit
- [ -nomercat ] %% don't use mercator projection
- [ -unconnect ] %% if multiple maps are concatenated
- %% this may be detected by the presence of
- %% a comment. if you activate this option,
- %% every block of comments that appears implies
- %% that the first pair of data points in the block
- %% should be treaten as the beginning of a new line.
- [ -showbox ] %% draw the bounding box
- [ -drawsegs ] %% do a 'stroke' after every line segment
- [ -debug ] %% print additional information
-
- NOTES: - If you specify both width and height this will result
- in a change of the image ratio, i.e. a distortion.
- - default unit is cm"
- - default origin is 0 0"
- - default width is original width\n"
-
- =====================================================================
-
- Compiled successfully on a SPARCstation running SunOS 4.1.1 with:
- gcc -O -o wmap2ps wmap2ps.c
-
- If you have problems compiling the program, you might need to change
- the lines where strings are concatenated over more than one line.
- I know that many compilers are not able to do that.
-
- =====================================================================
-
- .MP1 File Format: variable length ASCII records
-
- Data Records
- field
- 1 latitude floating point number
-
- 2 blank field separator
-
- 3 longitude floating point number
-
- [4] optional begining with a blank
- comment
-
- 5 line feed end of record (LF - 10)
-
- Separator Records
- field
- [1] optional blanks[s]
-
- 2 line feed end of record (LF - 10)
-
-
- All you have to do is
- - to draw a line from (x0,y0) to (x1,y1); the from (x1,y1) to (x2,y2) etc.
- - if a separator line (blank line) is read, break the connection,
-
- You may have noticed distortion in the maps displayed in the
- previous programs, epecially at extreme latitudes. This
- distortion is caused by an attempt to map the curved surface
- of a three dimensional globe onto a two dimensional plane. As
- you travel toward the poles, the 360 degrees of longitude are
- squeezed into less and less space on the globe, but not on the
- plane.
-
- There are many ways to compensate for the distortion problem.
- Probably the solution most widely recognized is the Mercator
- projection, named for a famous early map maker. Mercator's
- projection has the characteristics that both lines of latitude
- and longitude are straight and at right angles to each other
- (orthogonal). In addition, if a small area is viewed, there
- is no distortion of form: areas have the right shape although
- the vertical scale and total area is distorted as you move from
- the equator.
-
- The formula for the Mercator projection is
-
- y = ln{tan[45 deg + latitude/2)/deg_per_radian]}
-
- Check out the Encyclopedia Britannica under Map for all this
- good stuff and more.
-
- ========================================================================
-
- The data you may use with this tool can be found for example on host
-
- nz20.rz.uni-karlsruhe.de
-
- in the directory
-
- /pub/msdos/worldmap
-
- Just use archie and look for 'worldmap' in EXACT mode.
-
-
- =======================================================================
-
- As wmap2ps acts as a pipe, you may do the following
-
- cat AU0.MP1 AU1.MP1 AU2.MP1 | wmap2ps -unconnect -o 1 1 -w 6 > au.ps
-
- This would create a PostScript file that draws
- the map of Australia, its seas and its islands.
-
- If you glue together different maps in such a way, this may result in
- a map where the parts are connected by visible lines - to fix this
- problem you may want to add an extra separator line (blank line)
- at the end of the map files.
-
- =====================================================================
- cookies to RCS
- =====================================================================
-
- $Author: dockhorn $
- $Revision: 1.0 $
- $Log: wmap2ps.c,v $
- * Revision 1.0 92/09/05 18:06:07 dockhorn
- * Initial revision
- *
- */
-
- #include <stdio.h>
- #include <math.h>
-
- static char rcsid[] = "$Header: /disk/DBS0S3-2H/home/dockhorn/TOOLS/SRC/WMAP2PS/RCS/wmap2ps.c,v 1.0 92/09/05 18:06:07 dockhorn Exp Locker: dockhorn $";
-
- #define TEMPFILE "wmap2ps.tmp"
-
- #define Key(x) if (!(strcmp(argv[i],x)))
-
-
- /* primitive prototyping */
- void hints();
- int main();
- short rvalues();
- int check_arguments();
-
- /* print out the command line format */
-
- void hints(void)
- {
- fprintf(stderr,
- "\n\nwmap2ps [ -u unit ] /* one from { cm, in, pt } */"
- "\n [ -o x y ] /* lower left corner of image */"
- "\n [ -w width ] /* desired target width/height */"
- "\n [ -h height ] /* using the current unit */"
- "\n [ -nomercat ] /* don't use mercator projection */"
- "\n [ -unconnect ] /* don't draw illegal connections*/"
- "\n [ -showbbox ] /* draw the bounding box */"
- "\n [ -debug ] /* print additional information */\n"
- "\nNOTES: - If you specify both width and height this will result"
- "\n in a change of the image ratio, i.e. a distortion."
- "\n - default unit is cm"
- "\n - default origin is 0 0"
- "\n - default width is original width\n"
- "\nSee the manpage for more information.\n");
-
-
- }
-
- /* ok, ok, too many global variables,
- but here speed is more important than style
- and I lose enough speed by letting the
- program act as a pipe */
-
- #define BUFSIZE 80
- static int linecnt = 0; /* number of lines read */
- static short debug = 0; /* several flags */
-
- static float minlong = 1e10,minlat = 1e10, /* to compute bounding box */
- maxlong = -1e10, maxlat = -1e10,
- miny = 1e10, maxy = -1e10;
-
- static float llx = 0.0,lly = 0.0; /* user desired object origin */
-
- static char *unitnames[] = { "cm" , "in" , "pt" };
- static float unitfacts[] = { 28.34646, 72.0, 1.0 };
-
-
-
-
- /*
- read in two values from stdin.
- I use a procedure rather than fscanf to be able to cope with
- additional comments after the values, i.e. lines like
- -40.723 144.912 The World Digitized
- -40.781 144.891 Islands of Australia
- -40.801 144.896 Copyright 1986 John B. Allison
-
- the returned value tells me whether I should break the line
- connection or not.
- */
-
-
- short rvalues(ftmp,x,y,mercat)
- FILE *ftmp;
- float *x; /* longitude */
- float *y; /* latitude */
- short mercat; /* do conversion?*/
- {
- static unsigned char buf[BUFSIZE]; /* buffer for line read from file*/
- unsigned char c = (unsigned char) 0; /* current char read */
- unsigned char *tmp;
- float latitude,longitude;
- short idx = 0;
-
- c = fgetc(stdin);
- while ((!(feof(stdin))) && (c != '\n') && (idx < BUFSIZE))
- {
- buf[idx++] = c;
- c = (unsigned char) fgetc(stdin);
- }
-
- /* separator line ? */
- while ((idx > 0) &&
- ((buf[idx-1] == ' ') ||
- (buf[idx-1] == '\011') ||
- (buf[idx-1] == '\015')))
- buf[--idx] = (unsigned char) 0;
-
- if (!(feof(stdin)))
- {
- linecnt++;
- if (!(idx < BUFSIZE))
- fprintf(stderr,"\nSorry, line %d is too long.",linecnt);
- else
- {
- if (idx == 0) return(0); /* break line connection */
- buf[idx] = (unsigned char) 0;
- tmp = &buf[0];
- /* discard any control characters at the beginning of the buffer */
- while ((*tmp) && (*tmp < ' ')) tmp++;
- sscanf(tmp,"%g %g",&latitude,&longitude);
-
- if (latitude < miny) miny = latitude;
- if (latitude > maxy) maxy = latitude;
-
- if (mercat)
- {
- /* too close to pole -> don't project */
- if (!((fabs(latitude-90.0) < 1) ||
- (fabs(latitude-270.0) < 1)))
- latitude = (float) log(tan((45.0 +
- 0.5*(double)latitude)*M_PI/180.0));
- }
-
- /* bounding box changed ? */
- if (longitude < minlong) minlong = longitude;
- if (longitude > maxlong) maxlong = longitude;
- if (latitude < minlat) minlat = latitude;
- if (latitude > maxlat) maxlat = latitude;
-
- /* control output */
- if ((debug) && ((linecnt % 200) == 0))
- {
- fputc('.',stderr);
- fflush(stderr);
- }
-
- /* if there is a comment, print it to the output file */
- tmp = &buf[0];
- while ((*tmp) && (!(((*tmp >= 'a') && (*tmp <= 'z')) ||
- ((*tmp >= 'A') && (*tmp <= 'Z'))))) tmp++;
-
- *y = latitude;
- *x = longitude;
-
-
- if (*tmp)
- {
- fprintf(ftmp,"\n%% %s",tmp);
- return(2); /* comment encountered */
- }
- }
- }
- return(1);
- }
-
- /*
- parse command line arguments
- */
-
- int check_arguments(argc,argv,
- p_unitstr,p_unitfactor,
- p_width,p_height,
- p_mercat,p_unconnect,
- p_showbox,p_drawsegs)
- int argc;
- char *argv[];
- char **p_unitstr;
- float *p_unitfactor;
- float *p_width;
- float *p_height;
- short *p_mercat;
- short *p_unconnect;
- short *p_showbox;
- short *p_drawsegs;
- {
- int i,j;
- short hit;
-
- /* check for command line params */
- for (i = 1 ; i < argc ; i++)
- {
- if (*argv[i] != '-')
- {
- fprintf(stderr,
- "\nUnknown command line argument '%s' - abort.",
- argv[i]);
- hints();
- return(-1);
- }
- else
- switch(*(argv[i]+1))
- {
- case 'u':
- if (!(strcmp(argv[i]+1,"unconnect"))) *p_unconnect = 1;
- else
- {
- if (*(argv[i]+2) != (char) 0)
- {
- fprintf(stderr,
- "\nUnknown option '%s' - maybe '-u' was intended.",
- argv[i]);
- hints();
- return(-1);
- }
-
- i++;
- for (j = 0 , hit = 0; j < 3 ; j++)
- {
- Key(unitnames[j])
- {
- hit = 1;
- *p_unitstr = &unitnames[j][0];
- *p_unitfactor = unitfacts[j];
- }
- }
-
- if (!(hit))
- {
- fprintf(stderr,"\nUnknown unit '%s' requested.",argv[i]);
- hints();
- return(-1);
- }
- }
- break;
-
- case 'w' :
- case 'W':
- if (*(argv[i]+2) != (char) 0)
- {
- fprintf(stderr,
- "\nUnknown option '%s' - maybe '-w' was intended.",
- argv[i]);
- hints();
- return(-1);
- }
-
- if ((i+1) < argc)
- sscanf(argv[++i],"%g",p_width);
- else
- {
- fprintf(stderr,"\nMissing value after -w option - abort.");
- hints();
- return(-1);
- }
- break;
-
- case 'h' :
- case 'H':
- if (*(argv[i]+2) != (char) 0)
- {
- fprintf(stderr,
- "\nUnknown option '%s' - maybe '-w' was intended.",
- argv[i]);
- hints();
- return(-1);
- };
-
- if ((i+1) < argc)
- sscanf(argv[++i],"%g",p_height);
- else
- {
- fprintf(stderr,"\nMissing value after -h option - abort.");
- hints();
- return(-1);
- }
- break;
-
- case 'n':
- if (!(strcmp(argv[i]+1,"nomercat"))) *p_mercat = 0;
- else
- {
- fprintf(stderr,
- "\nUnknown option '%s' - maybe '-nomercat' was intended.",
- argv[i]);
- hints();
- return(-1);
- };
- break;
-
- case 's':
- if (!(strcmp(argv[i]+1,"showbox"))) *p_showbox = 1;
- else
- {
- fprintf(stderr,
- "\nUnknown option '%s' - maybe '-showbox' was intended.",
- argv[i]);
- hints();
- return(-1);
- };
- break;
-
- case 'd':
- if (!(strcmp(argv[i]+1,"debug"))) debug = 1;
- else
- {
- if (!(strcmp(argv[i]+1,"drawsegs")))
- *p_drawsegs = 1;
- else
- {
- fprintf(stderr,
- "\nUnknown option '%s'"
- "\n - maybe '-debug' or '-drawsegs' have been intended.",
- argv[i]);
- hints();
- return(-1);
- }
- }
-
- break;
-
- case 'o':
- if (*(argv[i]+2) != (char) 0)
- {
- fprintf(stderr,
- "\nUnknown option '%s' - maybe '-o' was intended.",
- argv[i]);
- hints();
- return(-1);
- }
- else
- {
- if ((i+2) < argc) /* arguments given ? */
- {
- sscanf(argv[++i],"%g",&llx);
- sscanf(argv[++i],"%g",&lly);
- }
- else
- {
- fprintf(stderr,
- "\nMissing values after '-o' - abort.");
- hints();
- return(-1);
- }
- }
- break;
-
- default :
- fprintf(stderr,
- "\nUnknown command line argument '%s' - abort.",
- argv[i]);
- hints();
- return(-1);
-
- } /* end switch */
- } /* end loop over command line options */
-
- return(0);
- /* ------------------ end of command line parsing------------------- */
- } /* end check_arguments() */
-
-
- /***********************************************************************/
- /***********************************************************************/
- /* M A I N */
- /***********************************************************************/
- /***********************************************************************/
-
- int main(argc, argv)
- int argc;
- char *argv[];
- {
- /* ============================= VARIABLES ========================== */
-
- float y,x,lx,ly; /* temporary location variables */
- float bwidth,bheight,blat; /* natural object size */
- float width = -1.0, height = -1.0; /* user desired object size */
-
- char *unitstr = unitnames[0];
- float unitfactor = unitfacts[0];
-
- short mercat = 1, showbox = 0, status,
- oldstatus = 0, drawsegs = 0, unconnect = 0;
- short isdrawn;
-
- FILE *ftmp = fopen(TEMPFILE,"w"); /* handle for temporary file */
-
- char c;
-
- /* possible units and their conversion values */
-
- /* =============================== CODE ============================= */
-
- if (check_arguments(argc,argv,
- &unitstr,&unitfactor,
- &width,&height,
- &mercat,&unconnect,
- &showbox,&drawsegs)) return(-1);
-
- llx*=unitfactor; /* convert origin to current unit */
- lly*=unitfactor;
-
- /* read stdin and write the data to a temporary
- file while looking for the bounding box */
-
- if (ftmp == (FILE *) NULL)
- {
- fprintf(stderr,
- "\nCouldn't open temporary file %s for writing - abort.\n",
- TEMPFILE);
- return(-1);
- }
-
-
- if (debug)
- {
- fprintf(stderr,
- mercat ? "\nUsing mercator projection." : "\nNo projection.");
- fprintf(stderr,"\nscanning");
- }
-
- /* -------------------------- conversion --------------------------- */
-
- rvalues(ftmp,&lx,&ly,mercat);
- fprintf(ftmp,"\n%g %g M",lx,ly);
-
- while (!(feof(stdin)))
- {
- status = rvalues(ftmp,&x,&y,mercat);
- isdrawn = 0;
-
- if ((status == 2) && (oldstatus == 1))
- {
- fprintf(stderr,
- "\nWarning ! I found a comment in line %d of the input file"
- "\n but no separator line before it. This might"
- "\n result in a line that interconnects different maps.\n",
- linecnt);
- if (unconnect)
- {
- fprintf(stderr,
- "As you gave the '-unconnect' option, I'll break the line here.\n");
- fprintf(ftmp,"\n%g %g M",x,y);
- isdrawn = 1;
- status = 0;
- }
- else
- fprintf(stderr,
- "You should check the file or specify the '-unconnect' option.\n");
- }
-
- /* a blank line means break line connection */
-
- if (status)
- fprintf(ftmp,"\n%g %g L",lx,ly,x,y);
- else
- {
- if (!(isdrawn))
- {
- while (!(status))
- {
- status = rvalues(ftmp,&x,&y,mercat); /* scan next starting point */
- if ((debug) && (!(status)))
- fprintf(stderr,"\nMultiple separators in line %d.\n",linecnt);
- }
- fprintf(ftmp,"\n%g %g M",x,y);
- }
- }
- lx = x; ly = y;
- oldstatus = status;
- }
-
- fclose(ftmp);
-
- /* -------------------------- computation --------------------------- */
-
- bwidth = maxlong - minlong; /* extents before scaling */
- bheight = maxy - miny;
- blat = maxlat - minlat;
-
- /* if neither -w nor -h was given, use original size */
-
- if ((height < 0.0) && (width < 0.0))
- {
- height = bheight;
- width = bwidth;
- unitfactor = 1.0;
- }
- else
- {
- if (height > 0.0)
- {
- /* compute width from desired height and object size */
- height*=unitfactor;
- if (width < 0.0) /* preserve ratio */
- width = bwidth*height/bheight;
- else
- width*=unitfactor; /* ok, that's what you wanted */
- }
- else
- {
- /* compute height from desired width and object size */
- width*=unitfactor;
- height = bheight*width/bwidth;
- }
- }
-
- if (debug)
- fprintf(stderr,
- "\n\nNumber of data points = %d"
- "\nSelected unit = %s"
- "\nBounding Box of given object = %6.1f %6.1f %6.1f %6.1f"
- "\nNatural size of object = %6.1f x %6.1f points"
- "\nScaling factors = %6.1f %6.1f"
- "\nSize of object after scaling = %6.1f x %6.1f points"
- "\n = %6.1f x %6.1f inches"
- "\n = %6.1f x %6.1f cm"
- "\nDesired origin = %6.1f , %6.1f points"
- "\n = %6.1f , %6.1f inches"
- "\n = %6.1f , %6.1f cm\n\n",
- linecnt,
- unitstr,
- minlong,minlat,maxlong,maxlat,
- bwidth,blat,
- width/bwidth,height/blat,
- width,height,
- width/72.0,height/72.0,
- width/28.34646,height/28.34646,
- llx,lly,
- llx/72.0,lly/72.0,
- llx/28.34646,lly/28.34646);
-
- /* write prologue */
-
- fprintf(stdout,
- "%%!PS-Adobe-2.0 EPSF-2.0"
- "\n%%%%Title: (unknown)"
- "\n%%%%Creator: wmap2ps by Patrick Dockhorn - WORLDMAP data (C) 1986 John B. Allison"
- "\n%%%%BoundingBox: %g %g %g %g"
- "\n%%%%Pages: 1"
- "\n%%%%DocumentFonts:"
- "\n%%%%EndComments"
- "\n%%%%EndProlog\n"
- "\n%% remember original state"
- "\n/origstate save def\n"
- "\n%% build a temporary dictionary"
- "\n20 dict begin\n"
- "\n%% scale to size desired by user"
- "\n%% (%g x %g points ="
- "\n%% %g x %g inches ="
- "\n%% %g x %g centimeter)"
- "\n%g %g scale\n"
- "\n%% set color to black and select thinnest line\n"
- "\n0 setlinewidth 0 setgray\n\n"
- "\n%c newpath %g %g moveto %g 0 rlineto %% show bounding box"
- "\n%c 0 %g rlineto %g 0 rlineto closepath stroke\n"
- "\n%% lower left corner"
- "\n%g %g translate\n"
- "\n/M {%smoveto } def"
- "\n/L { lineto%s} def\n",
- llx,lly,llx+width,lly+height,
- width,height,
- width/72.0,height/72.0,
- width/28.34646,height/28.34646,
- width/bwidth,height/blat,
- showbox ? ' ' : '%',
- (llx*bwidth/width),
- (lly*blat/height),bwidth,
- showbox ? ' ' : '%',
- blat,-1.0*bwidth,
- (llx*bwidth/width)-minlong,
- (lly*blat/height)-minlat,
- drawsegs ? " newpath " : " ",
- drawsegs ? " currentpoint stroke moveto " : " ");
-
-
-
- if ((ftmp = fopen(TEMPFILE,"r")) == (FILE *) NULL)
- {
- fprintf(stderr,
- "\nCouldn't open temporary file %s for reading - abort.\n",
- TEMPFILE);
- return(-1);
- }
-
- /* copy from temporary file to stdout */
-
- c = fgetc(ftmp);
- while (!(feof(ftmp)))
- {
- fputc(c,stdout);
- c = fgetc(ftmp);
- }
-
- /* write closing */
-
- fprintf(stdout,
- "%sshowpage"
- "\n%% stop using temporary dictionary"
- "\nend\n"
- "\n%% restore original state"
- "\norigstate restore"
- "\n\n%%%%Trailer\n",
- drawsegs ? "\n" : "\nstroke\n");
-
- unlink(TEMPFILE); /* remove temporary file */
- return(0);
- } /* end main */
-