home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume32 / wmap2ps / part01 / wmap2ps.c < prev   
C/C++ Source or Header  |  1992-09-11  |  20KB  |  741 lines

  1. /*
  2.    wmap2ps
  3.  
  4.    Description: converts files from the WORLDMAP package 
  5.                 (MP1 format) by John B. Allison to PostScript
  6.  
  7.    The program expects input from stdin in WORLDMAP format
  8.    as described below and writes a corresponding PostScript 
  9.    file to stdout.
  10.  
  11.    Written by Patsch in September 1992 (I needed the map of Tassie...)
  12.  
  13.    This program is in the Public Domain, as
  14.    long as the README file is kept intact.
  15.  
  16.    =====================================================================
  17.  
  18.    Usage :
  19.  
  20.           wmap2ps [ -u unit     ]   %% one from { cm, in, pt }     
  21.               [ -o x y      ]   %% lower left corner of image  
  22.               [ -w width    ]   %% desired target width/height 
  23.               [ -h height   ]   %% using the current unit      
  24.           [ -nomercat   ]   %% don't use mercator projection
  25.           [ -unconnect  ]   %% if multiple maps are concatenated
  26.                     %% this may be detected by the presence of
  27.                     %% a comment. if you activate this option,
  28.                     %% every block of comments that appears implies
  29.                     %% that the first pair of data points in the block
  30.                     %% should be treaten as the beginning of a new line.
  31.               [ -showbox    ]   %% draw the bounding box       
  32.           [ -drawsegs   ]   %% do a 'stroke' after every line segment
  33.               [ -debug      ]   %% print additional information
  34.  
  35.       NOTES:  - If you specify both width and height this will result
  36.                 in a change of the image ratio, i.e. a distortion.
  37.               - default unit is cm"
  38.               - default origin is 0 0"
  39.               - default width is original width\n"
  40.    
  41.    =====================================================================
  42.  
  43.    Compiled successfully on a SPARCstation running SunOS 4.1.1 with:
  44.    gcc -O -o wmap2ps wmap2ps.c
  45.    
  46.    If you have problems compiling the program, you might need to change
  47.    the lines where strings are concatenated over more than one line.
  48.    I know that many compilers are not able to do that.
  49.  
  50.    =====================================================================
  51.  
  52.    .MP1 File Format:  variable length ASCII records
  53.  
  54.        Data Records
  55.            field
  56.              1     latitude        floating point number
  57.  
  58.              2     blank           field separator
  59.  
  60.              3     longitude       floating point number
  61.  
  62.             [4]    optional        begining with a blank
  63.                       comment
  64.  
  65.              5     line feed       end of record (LF - 10)
  66.  
  67.       Separator Records
  68.            field
  69.             [1]    optional blanks[s]
  70.  
  71.              2     line feed       end of record (LF - 10)
  72.  
  73.  
  74.    All you have to do is
  75.    - to draw a line from (x0,y0) to (x1,y1); the from (x1,y1) to (x2,y2) etc.
  76.    - if a separator line (blank line) is read, break the connection,
  77.  
  78.      You may have noticed distortion in the maps displayed in the
  79.      previous programs, epecially at extreme latitudes.  This
  80.      distortion is caused by an attempt to map the curved surface
  81.      of a three dimensional globe onto a two dimensional plane.  As
  82.      you travel toward the poles, the 360 degrees of longitude are
  83.      squeezed into less and less space on the globe, but not on the
  84.      plane.
  85.  
  86.      There are many ways to compensate for the distortion problem.
  87.      Probably the solution most widely recognized is the Mercator
  88.      projection, named for a famous early map maker.  Mercator's
  89.      projection has the characteristics that both lines of latitude
  90.      and longitude are straight and at right angles to each other
  91.      (orthogonal).  In addition, if a small area is viewed, there
  92.      is no distortion of form: areas have the right shape although
  93.      the vertical scale and total area is distorted as you move from
  94.      the equator.
  95.      
  96.      The formula for the Mercator projection is
  97.  
  98.              y = ln{tan[45 deg + latitude/2)/deg_per_radian]}
  99.  
  100.      Check out the Encyclopedia Britannica under Map for all this
  101.      good stuff and more.
  102.  
  103.    ========================================================================
  104.  
  105.    The data you may use with this tool can be found for example on host
  106.  
  107.    nz20.rz.uni-karlsruhe.de
  108.  
  109.    in the directory
  110.  
  111.    /pub/msdos/worldmap
  112.  
  113.    Just use archie and look for 'worldmap' in EXACT mode.
  114.  
  115.  
  116.    =======================================================================
  117.  
  118.    As wmap2ps acts as a pipe, you may do the following
  119.  
  120.    cat AU0.MP1 AU1.MP1 AU2.MP1 | wmap2ps -unconnect -o 1 1 -w 6 > au.ps
  121.  
  122.    This would create a PostScript file that draws
  123.    the map of Australia, its seas and its islands.
  124.     
  125.    If you glue together different maps in such a way, this may result in
  126.    a map where the parts are connected by visible lines - to fix this 
  127.    problem you may want to add an extra separator line (blank line) 
  128.    at the end of the map files.
  129.  
  130.    =====================================================================
  131.                cookies to RCS
  132.    =====================================================================
  133.  
  134.    $Author: dockhorn $
  135.    $Revision: 1.0 $
  136.    $Log:    wmap2ps.c,v $
  137.  * Revision 1.0  92/09/05  18:06:07  dockhorn
  138.  * Initial revision
  139.  * 
  140. */
  141.  
  142. #include <stdio.h>
  143. #include <math.h>
  144.  
  145. 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 $";
  146.  
  147. #define TEMPFILE "wmap2ps.tmp"
  148.  
  149. #define Key(x) if (!(strcmp(argv[i],x)))
  150.  
  151.  
  152. /* primitive prototyping */
  153. void hints();
  154. int main();
  155. short rvalues();
  156. int check_arguments();
  157.  
  158. /* print out the command line format */
  159.  
  160. void hints(void)
  161. {
  162.   fprintf(stderr,
  163.           "\n\nwmap2ps [ -u unit     ]   /* one from { cm, in, pt }       */"
  164.       "\n        [ -o x y      ]   /* lower left corner of image    */"
  165.       "\n        [ -w width    ]   /* desired target width/height   */"
  166.       "\n        [ -h height   ]   /* using the current unit        */"
  167.       "\n        [ -nomercat   ]   /* don't use mercator projection */"
  168.       "\n        [ -unconnect  ]   /* don't draw illegal connections*/"
  169.       "\n        [ -showbbox   ]   /* draw the bounding box         */"
  170.       "\n        [ -debug      ]   /* print additional information  */\n"
  171.       "\nNOTES:  - If you specify both width and height this will result"
  172.       "\n          in a change of the image ratio, i.e. a distortion."
  173.       "\n        - default unit is cm"
  174.       "\n        - default origin is 0 0"
  175.       "\n        - default width is original width\n"
  176.       "\nSee the manpage for more information.\n");
  177.  
  178.   
  179. }
  180.  
  181. /* ok, ok, too many global variables, 
  182.    but here speed is more important than style
  183.    and I lose enough speed by letting the
  184.    program act as a pipe            */
  185.  
  186. #define BUFSIZE 80
  187. static int linecnt = 0;            /* number of lines read        */
  188. static short debug = 0;            /* several flags        */
  189.  
  190. static float minlong = 1e10,minlat = 1e10,   /* to compute bounding box     */
  191.              maxlong = -1e10, maxlat = -1e10,
  192.          miny = 1e10, maxy = -1e10;
  193.  
  194. static float llx = 0.0,lly = 0.0;       /* user desired object origin      */
  195.  
  196. static char *unitnames[] = { "cm" , "in" , "pt" };
  197. static float unitfacts[] = { 28.34646, 72.0, 1.0 };
  198.  
  199.  
  200.  
  201.  
  202. /*
  203.    read in two values from stdin.
  204.    I use a procedure rather than fscanf to be able to cope with
  205.    additional comments after the values, i.e. lines like
  206.    -40.723 144.912 The World Digitized
  207.    -40.781 144.891 Islands of Australia
  208.    -40.801 144.896 Copyright 1986 John B. Allison
  209.  
  210.    the returned value tells me whether I should break the line
  211.    connection or not.
  212. */
  213.  
  214.  
  215. short rvalues(ftmp,x,y,mercat)
  216. FILE *ftmp;
  217. float *x;    /* longitude     */
  218. float *y;    /* latitude    */
  219. short mercat;    /* do conversion?*/
  220. {
  221.   static unsigned char buf[BUFSIZE];        /* buffer for line read from file*/
  222.   unsigned char c = (unsigned char) 0;    /* current char read        */
  223.   unsigned char *tmp;
  224.   float latitude,longitude;
  225.   short idx = 0;
  226.  
  227.   c = fgetc(stdin);
  228.   while ((!(feof(stdin))) && (c != '\n') && (idx < BUFSIZE))
  229.     {
  230.       buf[idx++] = c;
  231.       c = (unsigned char) fgetc(stdin);
  232.     }
  233.   
  234.   /* separator line ? */
  235.   while ((idx > 0) && 
  236.      ((buf[idx-1] == ' ') || 
  237.       (buf[idx-1] == '\011') ||
  238.       (buf[idx-1] == '\015')))
  239.     buf[--idx] = (unsigned char) 0;
  240.  
  241.   if (!(feof(stdin)))
  242.     {
  243.       linecnt++;
  244.       if (!(idx < BUFSIZE))
  245.     fprintf(stderr,"\nSorry, line %d is too long.",linecnt);
  246.       else
  247.     {
  248.       if (idx == 0) return(0);    /* break line connection */
  249.       buf[idx] = (unsigned char) 0;
  250.       tmp = &buf[0];
  251.       /* discard any control characters at the beginning of the buffer */
  252.       while ((*tmp) && (*tmp < ' ')) tmp++;
  253.       sscanf(tmp,"%g %g",&latitude,&longitude);
  254.  
  255.       if (latitude < miny) miny = latitude;
  256.       if (latitude > maxy) maxy = latitude;
  257.  
  258.       if (mercat)
  259.         {
  260.           /*  too close to pole -> don't project */
  261.           if (!((fabs(latitude-90.0) < 1) ||  
  262.             (fabs(latitude-270.0) < 1)))
  263.         latitude = (float) log(tan((45.0 + 
  264.                         0.5*(double)latitude)*M_PI/180.0));
  265.         }
  266.  
  267.       /* bounding box changed ? */
  268.       if (longitude < minlong) minlong = longitude;
  269.       if (longitude > maxlong) maxlong = longitude;
  270.       if (latitude < minlat) minlat = latitude;
  271.       if (latitude > maxlat) maxlat = latitude;
  272.  
  273.       /* control output            */
  274.       if ((debug) && ((linecnt % 200) == 0))
  275.         {
  276.           fputc('.',stderr);
  277.           fflush(stderr);
  278.         }
  279.  
  280.       /* if there is a comment, print it to the output file */
  281.       tmp = &buf[0];
  282.       while ((*tmp) && (!(((*tmp >= 'a') && (*tmp <= 'z')) ||
  283.                   ((*tmp >= 'A') && (*tmp <= 'Z'))))) tmp++;
  284.  
  285.       *y = latitude;
  286.       *x = longitude;
  287.  
  288.  
  289.       if (*tmp)
  290.         {
  291.           fprintf(ftmp,"\n%% %s",tmp);
  292.           return(2);    /* comment encountered */
  293.         }
  294.     }
  295.     }
  296.   return(1);
  297. }
  298.  
  299. /*
  300.    parse command line arguments
  301. */
  302.  
  303. int check_arguments(argc,argv,
  304.             p_unitstr,p_unitfactor,
  305.             p_width,p_height,
  306.             p_mercat,p_unconnect,
  307.             p_showbox,p_drawsegs)
  308. int argc;
  309. char *argv[];
  310. char **p_unitstr;
  311. float *p_unitfactor;
  312. float *p_width;
  313. float *p_height;
  314. short *p_mercat;
  315. short *p_unconnect;
  316. short *p_showbox;
  317. short *p_drawsegs;
  318. {
  319.   int i,j;
  320.   short hit;
  321.  
  322.   /* check for command line params */
  323.   for (i = 1 ; i < argc ; i++)
  324.     {
  325.       if (*argv[i] != '-')
  326.     {
  327.       fprintf(stderr,
  328.           "\nUnknown command line argument '%s' - abort.",
  329.           argv[i]);
  330.       hints();
  331.       return(-1);
  332.     }
  333.       else
  334.     switch(*(argv[i]+1))
  335.       {
  336.       case 'u':
  337.         if (!(strcmp(argv[i]+1,"unconnect"))) *p_unconnect = 1;
  338.         else
  339.           {
  340.         if (*(argv[i]+2) != (char) 0)
  341.           {
  342.             fprintf(stderr,
  343.                 "\nUnknown option '%s' - maybe '-u' was intended.",
  344.                 argv[i]);
  345.             hints();
  346.             return(-1); 
  347.           }
  348.         
  349.         i++;
  350.         for (j = 0 , hit = 0; j < 3 ; j++)
  351.           {
  352.             Key(unitnames[j])
  353.               {
  354.             hit = 1;
  355.             *p_unitstr = &unitnames[j][0];
  356.             *p_unitfactor = unitfacts[j];
  357.               }
  358.           }
  359.         
  360.         if (!(hit))
  361.           {
  362.             fprintf(stderr,"\nUnknown unit '%s' requested.",argv[i]);
  363.             hints();
  364.             return(-1);
  365.           }
  366.           }
  367.         break;
  368.  
  369.       case 'w' :
  370.       case 'W':
  371.         if (*(argv[i]+2) != (char) 0)
  372.           {
  373.         fprintf(stderr,
  374.             "\nUnknown option '%s' - maybe '-w' was intended.",
  375.             argv[i]);
  376.         hints();
  377.         return(-1); 
  378.           }
  379.  
  380.         if ((i+1) < argc)
  381.           sscanf(argv[++i],"%g",p_width);
  382.         else
  383.           {
  384.         fprintf(stderr,"\nMissing value after -w option - abort.");
  385.         hints();
  386.         return(-1);
  387.           }
  388.         break;
  389.  
  390.       case 'h' :
  391.       case 'H':
  392.         if (*(argv[i]+2) != (char) 0) 
  393.           {
  394.         fprintf(stderr,
  395.             "\nUnknown option '%s' - maybe '-w' was intended.",
  396.             argv[i]);
  397.         hints();
  398.         return(-1); 
  399.           };
  400.           
  401.         if ((i+1) < argc)
  402.           sscanf(argv[++i],"%g",p_height);
  403.         else
  404.           {
  405.         fprintf(stderr,"\nMissing value after -h option - abort.");
  406.         hints();
  407.         return(-1);
  408.           }
  409.         break;
  410.  
  411.       case 'n':
  412.         if (!(strcmp(argv[i]+1,"nomercat"))) *p_mercat = 0;        
  413.         else
  414.           {
  415.         fprintf(stderr,
  416.             "\nUnknown option '%s' - maybe '-nomercat' was intended.",
  417.             argv[i]);
  418.         hints();
  419.         return(-1); 
  420.           };
  421.         break;
  422.  
  423.       case 's':
  424.         if (!(strcmp(argv[i]+1,"showbox"))) *p_showbox = 1;        
  425.         else
  426.           {
  427.         fprintf(stderr,
  428.             "\nUnknown option '%s' - maybe '-showbox' was intended.",
  429.             argv[i]);
  430.         hints();
  431.         return(-1); 
  432.           };
  433.         break;
  434.  
  435.       case 'd':
  436.         if (!(strcmp(argv[i]+1,"debug"))) debug = 1;
  437.         else
  438.           {
  439.         if (!(strcmp(argv[i]+1,"drawsegs")))
  440.           *p_drawsegs = 1;
  441.         else
  442.           {
  443.             fprintf(stderr,
  444.                 "\nUnknown option '%s'"
  445.                 "\n - maybe '-debug' or '-drawsegs' have been intended.",
  446.                 argv[i]);
  447.             hints();
  448.             return(-1);
  449.           }
  450.           }
  451.           
  452.         break;
  453.  
  454.       case 'o':
  455.         if (*(argv[i]+2) != (char) 0) 
  456.           {
  457.         fprintf(stderr,
  458.             "\nUnknown option '%s' - maybe '-o' was intended.",
  459.             argv[i]);
  460.         hints();
  461.         return(-1); 
  462.           }
  463.         else
  464.           {
  465.         if ((i+2) < argc)    /* arguments given ? */
  466.           {
  467.             sscanf(argv[++i],"%g",&llx);
  468.             sscanf(argv[++i],"%g",&lly);
  469.           }
  470.         else
  471.           {
  472.             fprintf(stderr,
  473.                 "\nMissing values after '-o' - abort.");
  474.             hints();
  475.             return(-1);
  476.           }
  477.           }
  478.         break;
  479.  
  480.         default :
  481.           fprintf(stderr,
  482.               "\nUnknown command line argument '%s' - abort.",
  483.               argv[i]);
  484.         hints();
  485.         return(-1);
  486.         
  487.       }    /* end switch */
  488.     }    /* end loop over command line options */
  489.  
  490.   return(0);
  491.   /* ------------------ end of command line parsing------------------- */
  492. }    /* end check_arguments()    */
  493.  
  494.  
  495. /***********************************************************************/
  496. /***********************************************************************/
  497. /*            M    A    I    N               */
  498. /***********************************************************************/
  499. /***********************************************************************/
  500.    
  501. int main(argc, argv)
  502. int argc;
  503. char *argv[];
  504. {
  505.   /* ============================= VARIABLES ========================== */
  506.  
  507.   float y,x,lx,ly;            /* temporary location variables */
  508.   float bwidth,bheight,blat;        /* natural object size        */
  509.   float width = -1.0, height = -1.0;    /* user desired object size    */
  510.  
  511.   char *unitstr = unitnames[0];
  512.   float unitfactor = unitfacts[0];
  513.  
  514.   short mercat = 1, showbox = 0, status, 
  515.         oldstatus = 0, drawsegs = 0, unconnect = 0;
  516.   short isdrawn;
  517.  
  518.   FILE *ftmp = fopen(TEMPFILE,"w");    /* handle for temporary file    */
  519.  
  520.   char c;
  521.  
  522.   /* possible units and their conversion values    */
  523.  
  524.   /* =============================== CODE ============================= */
  525.  
  526.   if (check_arguments(argc,argv,
  527.               &unitstr,&unitfactor,
  528.               &width,&height,
  529.               &mercat,&unconnect,
  530.               &showbox,&drawsegs)) return(-1);
  531.  
  532.   llx*=unitfactor;  /* convert origin to current unit    */
  533.   lly*=unitfactor;
  534.  
  535.   /* read stdin and write the data to a temporary 
  536.      file while looking for the bounding box    */
  537.  
  538.   if (ftmp == (FILE *) NULL)
  539.     {
  540.       fprintf(stderr,
  541.           "\nCouldn't open temporary file %s for writing - abort.\n",
  542.           TEMPFILE);
  543.       return(-1);
  544.     }
  545.  
  546.  
  547.   if (debug)
  548.     {
  549.       fprintf(stderr,
  550.           mercat ? "\nUsing mercator projection." : "\nNo projection.");
  551.       fprintf(stderr,"\nscanning");
  552.     }
  553.  
  554.   /* -------------------------- conversion --------------------------- */
  555.   
  556.   rvalues(ftmp,&lx,&ly,mercat);
  557.   fprintf(ftmp,"\n%g %g M",lx,ly);
  558.  
  559.   while (!(feof(stdin)))
  560.     {
  561.       status = rvalues(ftmp,&x,&y,mercat);
  562.       isdrawn = 0;
  563.  
  564.       if ((status == 2) && (oldstatus == 1))
  565.     {
  566.       fprintf(stderr,
  567.         "\nWarning ! I found a comment in line %d of the input file"
  568.         "\n          but no separator line before it. This might"
  569.         "\n          result in a line that interconnects different maps.\n",
  570.         linecnt);
  571.       if (unconnect)
  572.         {
  573.           fprintf(stderr,
  574.               "As you gave the '-unconnect' option, I'll break the line here.\n");
  575.           fprintf(ftmp,"\n%g %g M",x,y);
  576.           isdrawn = 1;
  577.           status = 0;
  578.         }
  579.       else
  580.         fprintf(stderr,
  581.             "You should check the file or specify the '-unconnect' option.\n");
  582.     }
  583.  
  584.       /* a blank line means break line connection */
  585.       
  586.       if (status)
  587.     fprintf(ftmp,"\n%g %g L",lx,ly,x,y);
  588.       else
  589.     {
  590.       if (!(isdrawn))
  591.         {
  592.           while (!(status))
  593.         {
  594.           status = rvalues(ftmp,&x,&y,mercat);    /* scan next starting point */
  595.           if ((debug) && (!(status)))
  596.             fprintf(stderr,"\nMultiple separators in line %d.\n",linecnt);
  597.         }
  598.           fprintf(ftmp,"\n%g %g M",x,y);
  599.         }
  600.     }
  601.       lx = x; ly = y;
  602.       oldstatus = status;
  603.     }
  604.  
  605.   fclose(ftmp);
  606.  
  607.   /* -------------------------- computation --------------------------- */
  608.  
  609.   bwidth = maxlong - minlong;    /* extents before scaling */
  610.   bheight = maxy - miny;
  611.   blat = maxlat - minlat;
  612.  
  613.   /* if neither -w nor -h was given, use original size */
  614.  
  615.   if ((height < 0.0) && (width < 0.0))
  616.     {
  617.       height = bheight;
  618.       width = bwidth;
  619.       unitfactor = 1.0;
  620.     }
  621.   else
  622.     {
  623.       if (height > 0.0)
  624.     {
  625.       /* compute width from desired height and object size */
  626.       height*=unitfactor;
  627.       if (width < 0.0)    /* preserve ratio */
  628.         width = bwidth*height/bheight;
  629.       else
  630.         width*=unitfactor;    /* ok, that's what you wanted    */
  631.     }
  632.       else
  633.     {
  634.       /* compute height from desired width and object size */
  635.       width*=unitfactor;
  636.       height = bheight*width/bwidth;
  637.     }
  638.     }
  639.  
  640.  if (debug)
  641.     fprintf(stderr,
  642.         "\n\nNumber of data points        = %d"              
  643.         "\nSelected unit                = %s"
  644.         "\nBounding Box of given object = %6.1f %6.1f %6.1f %6.1f"
  645.         "\nNatural size of object       = %6.1f x %6.1f points"
  646.         "\nScaling factors              = %6.1f   %6.1f"
  647.         "\nSize of object after scaling = %6.1f x %6.1f points"
  648.         "\n                             = %6.1f x %6.1f inches"
  649.         "\n                             = %6.1f x %6.1f cm"
  650.         "\nDesired origin               = %6.1f , %6.1f points"
  651.         "\n                             = %6.1f , %6.1f inches"
  652.         "\n                             = %6.1f , %6.1f cm\n\n",
  653.         linecnt,
  654.         unitstr,
  655.         minlong,minlat,maxlong,maxlat,
  656.         bwidth,blat,
  657.         width/bwidth,height/blat,
  658.         width,height,
  659.         width/72.0,height/72.0,
  660.         width/28.34646,height/28.34646,
  661.         llx,lly,
  662.         llx/72.0,lly/72.0,
  663.         llx/28.34646,lly/28.34646);
  664.  
  665.   /* write prologue */
  666.  
  667.   fprintf(stdout,
  668.       "%%!PS-Adobe-2.0 EPSF-2.0"
  669.       "\n%%%%Title: (unknown)"
  670.       "\n%%%%Creator: wmap2ps by Patrick Dockhorn - WORLDMAP data (C) 1986 John B. Allison"
  671.       "\n%%%%BoundingBox: %g %g %g %g"
  672.       "\n%%%%Pages: 1"
  673.       "\n%%%%DocumentFonts:"
  674.       "\n%%%%EndComments"
  675.       "\n%%%%EndProlog\n"
  676.       "\n%% remember original state"
  677.       "\n/origstate save def\n"
  678.       "\n%% build a temporary dictionary"
  679.       "\n20 dict begin\n"
  680.       "\n%% scale to size desired by user"
  681.       "\n%% (%g x %g points ="
  682.       "\n%%  %g x %g inches ="
  683.       "\n%%  %g x %g centimeter)"
  684.       "\n%g %g scale\n"
  685.       "\n%% set color to black and select thinnest line\n"
  686.       "\n0 setlinewidth 0 setgray\n\n"
  687.       "\n%c newpath %g %g moveto %g 0 rlineto %% show bounding box"
  688.       "\n%c 0 %g rlineto %g 0 rlineto closepath stroke\n"
  689.       "\n%% lower left corner"
  690.       "\n%g %g translate\n"
  691.       "\n/M {%smoveto } def"
  692.       "\n/L { lineto%s} def\n",
  693.       llx,lly,llx+width,lly+height,
  694.       width,height,
  695.       width/72.0,height/72.0,
  696.       width/28.34646,height/28.34646,
  697.       width/bwidth,height/blat,
  698.       showbox ? ' ' : '%',
  699.       (llx*bwidth/width),
  700.       (lly*blat/height),bwidth,
  701.       showbox ? ' ' : '%',
  702.       blat,-1.0*bwidth,
  703.       (llx*bwidth/width)-minlong,
  704.       (lly*blat/height)-minlat,
  705.       drawsegs ? " newpath " : " ",
  706.       drawsegs ? " currentpoint stroke moveto " : " ");
  707.  
  708.  
  709.  
  710. if ((ftmp = fopen(TEMPFILE,"r")) == (FILE *) NULL)
  711.     {
  712.       fprintf(stderr,
  713.           "\nCouldn't open temporary file %s for reading - abort.\n",
  714.           TEMPFILE);
  715.       return(-1);
  716.     }
  717.   
  718.   /* copy from temporary file to stdout */
  719.  
  720.   c = fgetc(ftmp);
  721.   while (!(feof(ftmp)))
  722.     {
  723.       fputc(c,stdout);
  724.       c = fgetc(ftmp);
  725.     }
  726.  
  727.   /* write closing */
  728.  
  729.   fprintf(stdout,
  730.       "%sshowpage"
  731.       "\n%% stop using temporary dictionary"
  732.       "\nend\n"
  733.       "\n%% restore original state"
  734.       "\norigstate restore"
  735.       "\n\n%%%%Trailer\n",
  736.       drawsegs ? "\n" : "\nstroke\n");
  737.  
  738.   unlink(TEMPFILE);    /* remove temporary file */
  739.   return(0);
  740. }    /* end main */
  741.