home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume13 / starchart / patch2 < prev    next >
Text File  |  1988-01-30  |  49KB  |  1,788 lines

  1. Subject:  v13i025:  Starchart package, Patch2
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: "Alan W. Paeth" <awpaeth@watcgl.waterloo.edu>
  7. Posting-number: Volume 13, Issue 25
  8. Archive-name: starchart/patch2
  9.  
  10. [  The starchart software was posted in Volume 12.  **MAKE SURE TO UNPACK
  11.    THIS IN A SEPARATE DIRECTORY or you will wipe out existing files!**  --r$ ]
  12.  
  13. # This is a shell archive.  Remove anything before this line,
  14. # then unpack it by saving it in a file and typing "sh file".
  15. # Contents:  starchart.1 starchart.c starchart.h stariris.c staruplot.c
  16.  
  17. echo x - starchart.1
  18. sed 's/^@//' > "starchart.1" <<'@//E*O*F starchart.1//'
  19. @.TH STARCHART LOCAL 9/22/87
  20. @.SH NAME
  21. stardsp, starpic, starpost, staruplot, startek, stariris, starhp, starlaser \- print astronomical star charts using Yale database.
  22. @.SH SYNOPSIS
  23. @.B star*
  24. RA DE [ scale title maglim lbllim ]
  25. @.br
  26. or
  27. @.br
  28. @.BI \-c\  constellation ...
  29. @.br
  30. or
  31. @.br
  32. @.BI \-r\  Ra
  33. @.BI \-d\  Dl
  34. [
  35. @.BI \-s\  scale
  36. @.BI \-t\  title
  37. @.BI \-m\  maglim
  38. @.BI \-l\  lbllim
  39. @.BI \-g\  grklim
  40. @.BI \-a\  (annotate)
  41. @.BI \-o\  (objects)
  42. @.BI \-b\  (bigchart)
  43. @.BI \-f\  ephem.star...
  44. @.BI \-y\  yale.star
  45. @.BI \-n\  messier.star
  46. @.BI \-w\  planet.star
  47. ]
  48. @.SH DESCRIPTION
  49. These programs generate star charts based on data extracted from the Yale
  50. public domain star catalog.
  51. Output is to the terminal 
  52. @.RI ( stardsp ),
  53. Unix PIC file format
  54. @.RI ( starpic ),
  55. PostScript format
  56. @.RI ( starpost ),
  57. Unix Plot(5) format
  58. @.RI ( staruplot ),
  59. Tektronix vector format
  60. @.RI ( startek ),
  61. Silicon Graphics Iris format
  62. @.RI ( stariris ),
  63. Hewlett-Packard terminal vector format
  64. @.RI (starhp)
  65. or in Hewlett-Packard Laserjet printer format
  66. @.RI ( starlaser ).
  67. @.PP
  68. Star data is optionally overlayed with other cosmic objects, such as planets.
  69. If limiting magnitudes are properly set and the Messier database is available,
  70. Messier objects and some NGC objects are also printed.
  71. @.PP
  72. The starchart center is specified by two parameters: Right
  73. Ascension [0.00 to 24.00 hours] and Declination [-90.00 to +90.00 degrees].
  74. An optional third parameter defines the N/S range of the output window, in
  75. degrees of declination.  Digits after decimal point are taken as minutes:
  76. object positions can therefore be taken directly from a star catalog.
  77. @.PP
  78. An optional fourth parameter gives a title.
  79. This conforms to the 'old' Yale star chart format.
  80. Two new parameters can be added after title,
  81. defining the magnitude limit and label printing magnitude limit.
  82. These are discussed below.
  83. All parameters can be given by using options,
  84. which offers more flexibility.
  85. Parameters are:
  86. @.TP
  87. @.B \-r
  88. Right ascension.
  89. @.TP
  90. @.B \-d
  91. Declination.
  92. @.TP
  93. @.B \-s
  94. Scale.
  95. @.TP
  96. @.B \-t
  97. Title. All these work as described above. Additional switches:
  98. @.TP
  99. @.B \-m
  100. Star limiting magnitude. This sets limits on the faintest stars displayed
  101. on the ``master'' view. Default limits are device driver dependent (more below).
  102. The ``thumbnail'' finder view is set to a related limit.
  103. @.TP
  104. @.B \-l
  105. Label limiting magnitude. The new Yale database contains both a small set of
  106. familiar names (for stars and special objects), plus an extensive list of
  107. labels (Greek Bayer letter or Flamsteed numbers). Star names (including planet
  108. names) always print for this small set. To avoid clutter, the labels may be
  109. omitted below a cut-off magnitude by specifying this value.
  110. @.TP
  111. @.B \-g
  112. Greek/Flamsteed annotation magnitude. Labels printed for stars dimmer than
  113. this value will use a Bayer or numerical label in favor of a proper name.
  114. The default (2.05) includes nearly all well-known proper names including
  115. Polaris, and excludes but a small number (such as Algol). Large values
  116. generate charts full of obscure Arabian names, small (zero or negative) values
  117. produce non-verbose charts, eg. ``a'', in Greek where possible, instead of
  118. ``Sirius''.
  119. @.TP
  120. @.B \-c
  121. A three or four character mnemonic follows, which is a search string for a
  122. matching line-item entry in the file
  123. @.IR con.locs .
  124. If found, then the
  125. initial values for Ra, Decl, Scale and Title are taken from that file.
  126. Because the command line is parsed from left to right, subsequent switches
  127. might change the scale, title, or otherwise fine-tune the new defaults.
  128. @.TP
  129. @.B \-f
  130. A list of files follow, each containing ephemerides in the .star format, which
  131. will overlay the output. This is also useful for generating constellation
  132. boundaries, Milky Way isophots, and planet or satellite tracks. (The .star
  133. format additionally includes records for vector and text annotation). Files
  134. are processed sequentially. Thus, order may take on meaning for devices which
  135. provide a 2-1/2D page description, such as PostScript.
  136. @.TP
  137. @.B \-b
  138. This switch provides a single full-page of output, without a thumbnail-sized
  139. finder chart. The legend placard is replaced with a single line banner giving
  140. title, right ascension, declination and limiting magnitude. This mode is
  141. useful for the construction of atlas pages. Because the page depicts the same
  142. vertical scale in degrees of declination, the output will cover a slightly
  143. reduced extent in right ascention.
  144. @.TP
  145. @.B \-a
  146. This switch provides annotation-only (text) output: all stars and non-stellar
  147. objects are omitted (including objects normally rendered by using alpha
  148. characters). Borders and legends are left undisturbed. This feature is useful
  149. in separating output detail, as when making (color) overhead transparencies.
  150. @.TP
  151. @.B \-o
  152. This switch provides object-only output, and is the complement of the
  153. above switch. When both switches appear together, all output is displayed.
  154. This resembles the default case (neither switch), except in that case object
  155. and annotation detail are written together. Here the software makes two
  156. consecutive passes through all datasets and arranges output detail to be
  157. written with all cosmic objects prefacing all related text annotations.
  158. This is useful in providing data for PostScript files in which rendering
  159. happens in a 2-1/2D back-to-front order, thus providing for a cleaner
  160. overlaying of output.
  161. @.TP
  162. @.B \-y \-w \-p
  163. These switches allow for the redefinition of the files yale.star, messier.star
  164. and planet.star, respectively.
  165. @.PP
  166. @.SH OUTPUT
  167. The present implementations draw two viewports: a ``master'' chart plus a
  168. ``thumbnail'' overview with low limiting magnitude.
  169. Their location and the limiting magnitude is specified by records in
  170. the device driver, allowing the chart layout be tuned on a per-device basis.
  171. In all cases, the output is annotated with viewport boundaries, a legend and
  172. axis labels. Variations are described for the
  173. @.B \-a \-o
  174. and
  175. @.B -b
  176. switches, above.
  177. @.PP
  178. Objects are drawn in glyphs defined by each display driver. Vector-only
  179. devices rely on the parent module ``starimages.c'' to provide shape tables;
  180. other devices plot special characters (stardsp or starpic) or private symbols
  181. (PostScript). The latter additionally provides distinctions between object
  182. subclasses, e.g. planetary vs diffuse nebula. The code provides for this
  183. generally, creation of new glyphs.
  184. @.PP
  185. Sanson's sinusoidal projection is used to map coordinates.
  186. This projection preserves both area and linearity in Declination (y axis).
  187. It gives good conformality (angle correctness) near the equator, so it is
  188. useful along the Ecliptic.
  189. Lines of RA converge at the poles (unlike cylindrical projections),
  190. though Cassiopeia and the Dipper reproduce well.
  191. @.SH EXAMPLES 
  192. @.nf
  193. # Sagittarius: a nice bunch of Messier objects.
  194. starpost -c sgr -a -o -t Sagittarius >sag.ps
  195. @.sp
  196. # Orion: the belt lies near 5h40m in RA, just below the CE.
  197. stardsp 5.32 -5 12 "Trapezium (Orion)" 8 5 | more
  198. @.fi
  199. @.SH FILES
  200. @.nf
  201. @.ta \w'messier.star    'u
  202. yale.star    stellar information (mandatory)
  203. messier.star    Messier objects (optional)
  204. planet.star    Planets (optional)
  205. con.locs    default mnemonic locations
  206. @.fi
  207. @.br
  208. @.sp
  209. These default paths can be easily changed in the Makefile.
  210. @.SH BUGS
  211. The present implementation expects
  212. @.I yale.star
  213. sorted by decreasing magnitude so that output is sequential, and then cuts off
  214. below a limiting magnitude.
  215. For more detailed charts spatial sorting might be more appropriate.
  216. No cutoff is performed for other .star files.
  217. @.PP
  218. If <minutes> part of the parameters is greater than 59 it is silently
  219. truncated to 59.
  220. @.PP
  221. All .star file coordinates are for epoch E2000.0.
  222. The Messier objects in
  223. @.I messier.star
  224. were taken from precessed E1975.0 data.
  225. The additional NGC objects were taken from data in the star atlas by
  226. @.I Norton
  227. and precessed from E1950.0.
  228. Descriptions and accurate magnitude values of all Messier objects were taken
  229. from the 1988 edition of the Royal Astronomical Society of Canada (RASC)
  230. handbook.
  231. @.SH FUTURE EXTENTIONS
  232. A
  233. @.B \-p
  234. switch will provide polar plotting; early code attempts using Stereographic
  235. projection have lacked the ability to draw the horizon lines and tick
  236. marks correctly. This and other extensions are discussed at the end of
  237. ``starchart.c'', and is suggested reading for anyone wishing to enhance
  238. the software.
  239. @.SH AUTHOR/EDITOR
  240. Alan Paeth, University of Waterloo (AWPaeth@watCGL)
  241. @.SH MAJOR CONTRIBUTORS
  242. Petri Launiainen (pl@intrin.FI)
  243. @.br
  244. Jyrki Yli-Nokari (jty@intrin.FI)
  245. @.br
  246. Robert Tidd (inp@violet.berkeley.edu)
  247. @.br
  248. Craig Counterman (ccount@royal.mit.edu)
  249. @//E*O*F starchart.1//
  250. chmod u=r,g=r,o=r starchart.1
  251.  
  252. echo x - starchart.c
  253. sed 's/^@//' > "starchart.c" <<'@//E*O*F starchart.c//'
  254. /*
  255.  * starchart.c -- version 2, September 1987
  256.  *        revision 2.1 December, 1987
  257.  *
  258.  * (c) copyright 1987 by Alan Paeth (awpaeth@watcgl)
  259.  */
  260.  
  261. /*
  262.  ! Version 2 modification authors:
  263.  !
  264.  !   [a] Petri Launiainen, pl@intrin.FI (with Jyrki Yli-Nokari, jty@intrin.FI)
  265.  !   [b] Bob Tidd, inp@VIOLET.BERKELEY.EDU
  266.  !   [c] Alan Paeth, awpaeth@watcgl
  267.  !
  268.  ! Changes and Additions:
  269.  !
  270.  !a   [1] STARFILE, PLANETFILE, etc. path designations are now in the Makefile
  271.  !ac  [2] Fractional Ra and Decl values are now hh.mm and mm.ss (base 60)
  272.  !a   [3] Command syntax now allows flags as well as old style (arg placement)
  273.  !ab  [4] Extended Yale database (courtesy B. Tidd) also supported on input
  274.  !bc  [5] Greek+Flamsteed numbers now appear as a hardcopy annotation
  275.  !bc  [6] Constellation file finds ra,dl,scale from command line pattern
  276.  !c   [7] New symbols for Nebulae, Galaxies and Clusters added (based on [4])
  277.  !c   [8] Double star indications added (provisions for variable stars) ([4])
  278.  !a   [9] Limiting magnitude flags for stars and labels allowed
  279.  !c  [10] Legend column reformatted to contain additional symbols [4]
  280.  !a  [11] Internal symbol compiler created for raster glyph creation
  281.  !c  [12] add Yale records for "moveto"/"drawto" and text annotations
  282.  !c  [13] added -f file.star to add ephemeride data
  283.  !
  284.  ! Bug Fixes:
  285.  !
  286.  !a   [1] no more core dumps (on SysV) when given bad command line parameters
  287.  !c   [2] Negative RA indications now "wrap" to 24hrs, etc.
  288.  !bc  [3] Mag values *rounded* to nearest unit value (common Atlas convention)
  289.  !c   [4] Removed any device dependent subroutines (eg. getopt).
  290.  !
  291.  ! Final integration by the original author [c].
  292.  ! Questions, suggestions, and fixes should be e-mailed to him.
  293.  */
  294.  
  295.  /* Version 2.1 patches
  296.  !
  297.  ! patched December, 1987 by Alan Paeth (awpaeth@watcgl),
  298.  ! based on revisions by Craig Counterman (ccount@royal.mit.edu)
  299.  ! et al.
  300.  !
  301.  ! [1] clipping of scaling, ra and decl now takes place
  302.  ! [2] negative magnitude bug fixed; plus format change to yale.star
  303.  ! [3] string arrays ras[2] changed to ras[20] (typo in "chartlegend()")
  304.  ! [4] scanf now uses %f and floats exclusively (for IRIS and sysV)
  305.  ! [5] bigmaster facility added for full-page output
  306.  ! [6] multiple .star files now accepted by -f flag
  307.  ! [7] the -y flag allows overriding of default yale.star dataset
  308.  ! [8] the -n flag allows overriding of default messier.star dataset
  309.  ! [9] the -w flag allows overriding of default planet.star dataset
  310.  ![10] the -a and -o flags allow for separate/sorted object/annotation detail
  311.  ![11] the -g flag sets a mag limit for star proper names, else use codes
  312.  */
  313.  
  314. #include <stdio.h>
  315. #include <math.h>
  316. #ifndef SYSV
  317. #include <strings.h>
  318. #else
  319. #include <string.h>
  320. #endif
  321. #include <ctype.h>
  322. #include "starchart.h"
  323.  
  324. /*
  325.  * default datasets are local, unless defined in Makefile
  326.  */
  327.  
  328. #ifndef STARFILE
  329. #define STARFILE    "./yale.star"
  330. #endif
  331.  
  332. #ifndef PLANETFILE
  333. #define PLANETFILE    "./planet.star"
  334. #endif
  335.  
  336. #ifndef MESSFILE
  337. #define MESSFILE    "./messier.star"
  338. #endif
  339.  
  340. #ifndef CONSTFILE
  341. #define CONSTFILE    "./con.locs"
  342. #endif
  343.  
  344.  
  345. #define DCOS(x) (cos((x)*3.14159265354/180.0))
  346. #define MAX(a,b) ((a)>(b)?(a):(b))
  347. #define MIN(a,b) ((a)<(b)?(a):(b))
  348. #define FALSE 0
  349. #define TRUE 1
  350.  
  351. #define MAXUFILES 10    /* Maximum number of user supplied files */
  352. #define THUMBDIFF 2.5    /* thumbnail mag lim is brighter */
  353. #define THUMBMAX 5.0    /* but no lower than this value */
  354. #define THUMBRATIO 1.2    /* and scaled by this size (yet is already wider) */
  355. #define THUMBDEG 10.0    /* but this is the floor on finder scale */
  356. #define FSIZESML 8    /* point size for star designation */
  357. #define FSIZELRG 10    /* point size for other object annotations */
  358.  
  359. float max(), modup(), moddown();
  360. float ftod(), htod();
  361. /* double atof(); */        /* possible system compatability problem */
  362.  
  363. /* globals */
  364.  
  365. char *progname;            /* program name for errors */
  366. float ra, de, sc;        /* global chart attributes */
  367. char *title;
  368. char *starfile = STARFILE;
  369. char *planetfile = PLANETFILE;
  370. char *messfile = MESSFILE;
  371. char *constfile = CONSTFILE;
  372. char *userfile[MAXUFILES];    /* potential .star file of user ephemerides */
  373. int nufiles = 0;        /* number of userfiles */
  374. int bigflag = FALSE;        /* chart page only, no thumbnail or legend */
  375. int annodetail, objdetail;    /* flags to control output */
  376. int annoswitch, objswitch;    /* switches as seen on command line */
  377. float olat, olon;        /* save areas for track clipping */        
  378.  
  379. /* the code */
  380.  
  381. main(argc, argv)
  382.     int argc;
  383.     char *argv[];
  384.     {
  385.     int chartpasses, chartcount;
  386.  
  387.     commandline(argc, argv);
  388. /*
  389.  * copy command line defaults into all possible charts
  390.  */
  391.     thumbnail.lbllim = bigmaster.lbllim = master.lbllim;
  392.     thumbnail.maglim = bigmaster.maglim = master.maglim;
  393.     thumbnail.gklim = bigmaster.gklim  = master.gklim;
  394. /*
  395.  * drawing order:
  396.  *
  397.  * (1) chart outlines
  398.  * (2) stars a/o
  399.  * (3) annotations
  400.  * (4) legend
  401.  */
  402.     vecopen();
  403.     chartparms(&master, sc);
  404.     chartparms(&bigmaster, sc);
  405. /*
  406.  * thumbnail gets fine-tuned scale and brighter limiting magnitude
  407.  */
  408.     chartparms(&thumbnail, MAX(sc * THUMBRATIO, THUMBDEG));
  409.     thumbnail.maglim = MIN(THUMBMAX, master.maglim - THUMBDIFF);
  410. /*
  411.  * background stuff
  412.  */
  413.     annodetail = TRUE;        /* no omissions on background */
  414.     objdetail = TRUE;
  415.     if (bigflag) chartbackground(&bigmaster);
  416.     else
  417.     {
  418.     chartbackground(&master);
  419.     chartbackground(&thumbnail);
  420.     }
  421. /*
  422.  * main drawing
  423.  */
  424.     chartpasses = (annoswitch && objswitch) ? 2 : 1;
  425.     if (!annoswitch && !objswitch) annoswitch = objswitch = TRUE; /* default */
  426.     for(chartcount=0; chartcount<chartpasses; chartcount++)
  427.     {
  428. /*
  429.  * set detail control flags from command line switches and pass number
  430.  */
  431.     annodetail = annoswitch;
  432.     objdetail =  objswitch;
  433.     if ((chartpasses == 2) && (chartcount == 0)) annodetail = FALSE;
  434.     if ((chartpasses == 2) && (chartcount == 1)) objdetail = FALSE;
  435. /*
  436.  * drawing
  437.  */
  438.     if (bigflag) chartall(&bigmaster);
  439.     else
  440.         {
  441.         chartall(&master);
  442.         chartall(&thumbnail);
  443.         }
  444. /*
  445.  * (mini)legend
  446.  */
  447.     annodetail = TRUE;    /* legend has no omissions */
  448.     objdetail = TRUE;
  449.     if (bigflag) chartbanner(&bigmaster);
  450.     else chartlegend(&master);
  451.     }
  452.     vecclose();
  453.     exit(0);
  454.     }
  455.  
  456. commandline(argc, argv)
  457.     char *argv[];
  458.     {
  459.     int j;
  460.     static char *usage =
  461. "\nusage:\tstar* [ Ra Dcl Scale Title Maglim Labellim ]\nor\tstar* [ -r Ra -d Dcl -s Scale -t Title -m Maglim -l Labellim -f x.star ]\nor\tstar*  [ -c con (3 or 4 letters chosen from con.locs) -l ... ]";
  462.     progname = argv[0];
  463.     title = NULL;
  464.     annoswitch = objswitch = FALSE;
  465.     ra = 0.0;
  466.     de = 0.0;
  467.     sc = 0.0;
  468. /*
  469.  * check command line style
  470.  */
  471.     if (argc == 1) die("No arguments - %s", usage);
  472.     if  ( (argv[1][0] == '-') && isalpha(argv[1][1]) )
  473.     {
  474. /*
  475.  * new style command line (using flags)
  476.  */
  477.     for (j=1; j<argc; j++)
  478.         {
  479.         if (argv[j][0] != '-') die("unknown argument - %s", argv[j]);
  480.         switch (argv[j][1])
  481.         {
  482.         case 'c':    /* could be -c con or -c con con.locs */
  483.             if (((j+2) < argc) && (argv[j+2][0] != '-'))
  484.             {
  485.             constfile = argv[j+2];
  486.             findconst(argv[++j]);
  487.             j++;
  488.             }
  489.             else findconst(argv[++j]);
  490.             break;
  491.         case 'r': ra = htod(argv[++j]); break;
  492.         case 'd': de = htod(argv[++j]); break;
  493.         case 's': sc = atof(argv[++j]); break;
  494.         case 'l': master.lbllim = (float)(atof(argv[++j])); break;
  495.         case 'm': master.maglim = (float)(atof(argv[++j])); break;
  496.         case 'g': master.gklim  = (float)(atof(argv[++j])); break;
  497.         case 't': title = argv[++j]; break;
  498.         case 'f': userfile[nufiles++] = argv[++j];
  499.               if (nufiles >= MAXUFILES) die("too many -f files");
  500.               break;
  501.         case 'u': die("%s", usage); break;
  502.         case 'y': starfile = argv[++j]; break;
  503.         case 'n': messfile = argv[++j]; break;
  504.         case 'w': planetfile = argv[++j]; break;
  505. /*        case 'p': polarmode = TRUE; break; */    /* someday! */
  506.         case 'b': bigflag = TRUE; break;
  507.         case 'a': annoswitch = TRUE; break;
  508.         case 'o': objswitch = TRUE; break;
  509.         default:  die("unknown switch - %s", argv[j]); break;
  510.         }
  511.         if (j == argc) die("trailing command line flag - %s", argv[j-1]);
  512.         }
  513.     }
  514.     else
  515.     {
  516. /*
  517.  * old style command line (position dependent)
  518.  */
  519.     switch (argc)
  520.         {
  521.         case 7: master.maglim = atof(argv[6]);
  522.         case 6: master.lbllim = atof(argv[5]);
  523.         case 5: title = argv[4];
  524.         case 4: sc = atof(argv[3]);
  525.         case 3: de = htod(argv[2]);
  526.         case 2: ra = htod(argv[1]); break;
  527.         default: die("too many arguments - %s", usage);
  528.         }
  529.     }
  530.     }
  531.  
  532. float ftod(x)
  533.     float x;
  534.     {
  535.     int full;
  536.     full = x;
  537.     return(full + (x-full)*100.0/60.0);
  538.     }
  539.  
  540. float htod(s)
  541.     char *s;
  542.     {
  543. /*
  544.  * htod(str) reads floating point strings of the form {+-}hh.{mm} thus
  545.  * allowing for fractional values in base 60 (ie, degrees/minutes).
  546.  */
  547. /*
  548.     float x, sign;
  549.     int full, frac;
  550.     char *t;
  551.     t = s-1;
  552.     while(*++t)
  553.     {
  554.     if ((*t == ' ') || (*t = '\t') || (*t == '\n')) break;
  555.     if ( ( (*t<'0') || (*t>'9') ) && (*t!='.') && (*t!='+') && (*t!='-'))
  556.         die("non-digit in dd.mm style numeric argument: %s", s);
  557.     }
  558.     if (s == NULL) return 0.0;
  559.     full = frac = 0;
  560.     sign = 1.0;
  561.     if (*s == '-')
  562.     {
  563.     sign = -1.0;
  564.     s++;
  565.     }
  566.     else if (*s == '+') s++;
  567.     while (*s && *s != '.') full = 10 * full + *s++ - '0';
  568.     if (*s++ == '.')
  569.     {
  570.     if (*s) frac = 10 * (*s++ - '0');
  571.     if (*s) frac += *s++ - '0';
  572.     if (frac > 59) frac = 59;
  573.     }
  574.     x = (float) full + ((float) frac) / 60.0;
  575.     return sign * x;
  576. */
  577.     return(ftod(atof(s)));
  578.     }
  579.  
  580. chartparms(chart, scl)
  581.     float scl;
  582.     map chart;
  583.     {
  584.     float maxdl, adj, xscale;
  585. /*
  586.  * check for bogus ra or decl
  587.  */
  588.     if ((ra >= 24.0) || (ra <    0.0)) die("right ascension out of range");
  589.     if ((de >= 90.0) || (ra <= -90.0)) die("declination out of range");
  590. /*
  591.  * record chart location
  592.  */
  593.     chart->racen = ra * 360.0 / 24.0;
  594.     chart->dlcen = de;
  595.     chart->scale = scl;
  596.     if (chart->scale == 0.0) chart->scale = 15.0;
  597. /*
  598.  * check for pole wrapping and do a potential clip
  599.  */
  600.     maxdl = (90.0 - chart->dlcen)*2.0;
  601.     if (chart->scale > maxdl) chart->scale = maxdl;
  602. /*
  603.  * locate chart limits
  604.  */
  605.     chart->north = (chart->dlcen + chart->scale / 2.0);
  606.     chart->south = (chart->dlcen - chart->scale / 2.0);
  607. /*
  608.  * xscale is other than chart->scale in order to widen the horizontal viewing
  609.  * area, which otherwise shrinks near the poles under Sanson's projection
  610.  * this happens in polar maps which do not span the celestial equator
  611.  */
  612.     adj = 1.0;
  613.     if (chart->north * chart->south > 0.0)
  614.     adj = max(DCOS(chart->north), DCOS(chart->south));
  615.     xscale = chart->scale/adj;
  616.  
  617.     chart->east  = (chart->racen + xscale*chart->ww/chart->wh / 2.0);
  618.     chart->west  = (chart->racen - xscale*chart->ww/chart->wh / 2.0);
  619.     chart->yscale = chart->wh / chart->scale;
  620.     }
  621.  
  622. chartlegend(chart)
  623.     map chart;
  624.     {
  625.     char ras[20], dls[20], outstr[40];
  626.     if (!title) title = "LEGEND";
  627.     rastr(ras, chart->racen);
  628.     declstr(dls, chart->dlcen);
  629.     sprintf(outstr, "(%s,%s lim: %2.1f)", ras, dls, chart->maglim);
  630. /*
  631.  * there are reports that large point sizes (eg "16", below) cause characters
  632.  * to overlap on some (pic?) output devices. To fix, set values to "10".
  633.  */
  634.     pvecsize(16); pvecsyms(65, 220, title);
  635.     pvecsize(10); pvecsyms(65, 185, outstr);
  636.  
  637.     pdrawStar( 65, 150, 0, 'S', NULL);
  638.     pvecsize(12);
  639.     pvecsyms(  95, 150,"<0.5");
  640.     if (chart->maglim >= 0.5)
  641.     {
  642.     pdrawStar(230, 150, 1, 'S', NULL);
  643.     pvecsize(10);
  644.     pvecsyms( 260, 150,"<1.5");
  645.     }
  646.     if (chart->maglim >= 1.5)
  647.     {
  648.     pdrawStar( 65, 125, 2, 'S', NULL);
  649.     pvecsize( 9);
  650.     pvecsyms(  95, 125,"<2.5");
  651.     }
  652.     if (chart->maglim >= 2.5)
  653.     {
  654.     pdrawStar(230, 125, 3, 'S', NULL);
  655.     pvecsize( 8);
  656.     pvecsyms(260, 125,"<3.5");
  657.     }
  658.     if (chart->maglim >= 3.5)
  659.     {
  660.     pdrawStar( 65, 100, 4, 'S', NULL);
  661.     pvecsize( 7);
  662.     pvecsyms(  95, 100,"<4.5");
  663.     }
  664.     if (chart->maglim > 4.5)
  665.     {
  666.     pdrawStar(230, 100, 5, 'S', NULL);
  667.     pvecsize( 6);
  668.     pvecsyms(260, 100,">4.5");
  669.     }
  670.  
  671.     pvecsize(10); pvecsyms( 95,75,"double");   pdrawStar( 65,75, 2, 'D', NULL);
  672.     pvecsize(10); pvecsyms(260,75,"variable"); pdrawStar(230,75, 2, 'V', NULL);
  673.     pvecsize(10); pvecsyms( 95,50,"planet");   pdrawPlan( 65,50, 1, 'S', NULL);
  674.     pvecsize(10); pvecsyms(260,50,"galaxy");   pdrawGalx(230,50, 1, 'E', NULL);
  675.                            pdrawGalx(205,50, 1, 'S', NULL);
  676.     pvecsize(10); pvecsyms( 95,25,"nebula");   pdrawNebu( 65,25, 1, 'D', NULL);
  677.                            pdrawNebu( 40,25, 1, 'P', NULL);
  678.     pvecsize(10); pvecsyms(260,25,"cluster");  pdrawClus(230,25, 1, 'O', NULL);
  679.                            pdrawClus(205,25, 1, 'G', NULL);
  680.     }
  681.  
  682. chartbanner(chart)
  683.     map chart;
  684.     {
  685.     char ras[20], dls[20], outstr[100];
  686.     if (!title) title = "LEGEND";
  687.     rastr(ras, chart->racen);
  688.     declstr(dls, chart->dlcen);
  689.     pvecsize(8);
  690.     sprintf(outstr, "%s: %s,%s lim: %2.1f", title, ras, dls, chart->maglim);
  691.     pvecsyms(15, 15, outstr);
  692.     }
  693.  
  694. readstar(file, lat, lon, mag, code, subcode, color, label, name)
  695.     FILE *file;
  696.     float *lat, *lon, *mag;
  697.     char *code, *subcode, *color, *label, *name;
  698.     {
  699. #define LINELEN 80
  700.     char sbuf[LINELEN+1], *ptr;
  701.     float rah, ram, ras, dld, dlm, dl, inten;
  702.     int len, i;
  703. /*
  704.  * file formats:
  705.  * new
  706. 064509-1643-14SDA1a CMASirius
  707. 051432-0812015SDB8b ORIRigel
  708.  * old
  709. 064509-1643-146SSSirius
  710. 051432-08120015SSRigel
  711.  */
  712.     fgets(sbuf, LINELEN, file);
  713.     if (feof(file)) return(1);
  714. /*
  715.  * sscanf of floats is TOOO slow:
  716.  *     sscanf(sbuf, "%2f%2f%2f%c%2f%2f ... );
  717.  * use alternate:
  718.  */
  719. #define F2(i) ((float)((sbuf[i]-'0')*10+sbuf[i+1]-'0'))
  720. #define F3(i) ((float)((sbuf[i]-'0')*100+(sbuf[i+1]-'0')*10+sbuf[i+2]-'0'))
  721. #define F4(i) ((float)((sbuf[i]-'0')*1000+(sbuf[i+1]-'0')*100+(sbuf[i+2])-'0')*10+sbuf[i+3]-'0')
  722.     rah = F2(0);
  723.     ram = F2(2);
  724.     ras = F2(4);
  725.     dld = F2(7);
  726.     dlm = F2(9);
  727. /*
  728.  * common code
  729.  */
  730. #define DLDEGSEC 3600.0
  731. #define DLMINSEC 60.0
  732. #define RAHRSSEC 54000.0
  733. #define RAMINSEC 900.0
  734. #define RASECSEC 15.0
  735.  
  736.     *lon = (RAHRSSEC*rah + RAMINSEC*ram + RASECSEC*ras)/DLDEGSEC;
  737.     dl = (DLDEGSEC*dld + DLMINSEC*dlm)/DLDEGSEC;
  738.     *lat = (sbuf[6]  == '-') ? -dl : dl;
  739.     if  (isdigit(sbuf[14]))
  740.     {
  741. /*
  742.  * old reduced Yale catalog
  743.  */
  744.     inten = F3(12);
  745.     if (sbuf[11] == '0' || sbuf[11] == '+') *mag = inten/100.0;
  746.     else if (sbuf[11] == '-') *mag = -inten/100.0;
  747.     else *mag = F4(11)/1000.0;    /* new feature for stars >= 10.0 mag */
  748.     if (sbuf[11] != 0)
  749.     code[0] = sbuf[15];
  750.     subcode[0] = sbuf[16];
  751.     color [0] = '\0'; strcpy (color, "  "); /* set unknowns to blanks */
  752.     label [0] = '\0';
  753.     name [0] = '\0'; strncat (name, &sbuf[17], strlen (&sbuf [17]) - 1);
  754.     }
  755.     else
  756.     {
  757. /*
  758.  * new reduced Yale catalog
  759.  */
  760.     *mag = ((sbuf[11] == '-') ? -F2(12)/10.0 : F3(11))/100.0;
  761.     code[0] = sbuf[14];    /* let's get Sirius */
  762.     subcode[0] = sbuf[15];
  763.     color [0] = '\0';
  764.     label [0] = '\0';
  765.     name [0] = '\0';
  766.     switch (code[0])
  767.         {
  768.         case 'C':
  769.         case 'N':
  770.         case 'G':
  771. /*
  772.  * name vs label:
  773.  *
  774.  * A "name" is a common English term for a star or cosmic object (eg Polaris,
  775.  * Pleiades). A label is an official designation for such an object (eg
  776.  * alpha-Ursa Minor, M45). For stars, labels are taken from the two column
  777.  * Bayer/Flamsteed field in the new reduced label format and the proper name
  778.  * from the "name" field (the label field might also include the three letter
  779.  * IAU constellation designation, but at present these are ignored)
  780.  *
  781.  * For non-stellar objects, the Bayer and IAU fields are typically blank (and
  782.  * always ignored), and the "name" field consists of the designation followed
  783.  * by an optional proper name, or perhaps just an annotation, the latter
  784.  * flagged by a leading "," and ignored by the software. For instance, the
  785.  * entry "m45 Pleiades" forms a label "m45" and a name "Pleiades", but the
  786.  * entry "m6  ,butterfly shape" forms merely the label "m6".
  787.  *
  788.  * At the present, the charting software which is supplied this data on a call
  789.  * to "readstar" will print names in favor of labels.
  790.  */
  791. /*
  792.  * extract Messier number and name
  793.  */
  794.         strcpy (color, "  ");
  795.         ptr = &sbuf[23];
  796.         i = 0;
  797.         while (isalnum (*ptr)) label[i++] = *ptr++;
  798.  
  799.         label[i] = '\0';
  800.         i = 0;
  801.         while (*ptr == ' ') ptr++;
  802.         while (*ptr != ',' && *ptr != '\n' && *ptr)
  803.             name[i++] = *ptr++;
  804.         name[i] = '\0';
  805.         break;
  806.     default:
  807. /*
  808.  * extract color, label and name
  809.  */
  810.         strncat (color, &sbuf[16], 2);
  811.         strncat (label, &sbuf[18], strlen (&sbuf [18]) - 1);
  812.         if  ((len = strlen (label)) > 5)
  813.             {
  814.             strncat (name, &label[5], len - 5);
  815.             label [5] = '\0';
  816.             }
  817.         }
  818.     }
  819.     return(0);
  820.     }
  821.  
  822. xform(chart, lat, lon, xloc, yloc)
  823.     map chart;
  824.     float lat, lon;
  825.     int *xloc, *yloc;
  826.     {
  827.  /*
  828.   * This is Sanson's Sinusoidal projection. Its properties:
  829.   *   (1) area preserving
  830.   *   (2) preserves linearity along y axis (declination/azimuth)
  831.   */
  832.     *xloc = chart->wx+chart->ww/2 + (chart->racen-lon)*chart->yscale*DCOS(lat);
  833.     *yloc = chart->wy + (int)((lat - chart->south) * chart->yscale);
  834.     }
  835.  
  836. chartall(chart)
  837.     map chart;
  838.     {
  839. /*
  840.  * we might "die" after drawing the borders, but we want stars to overlay
  841.  * the border for imaging software which may handle the bottom-up 2-1/2D
  842.  * order of printing correctly (eg PostScript).
  843.  */
  844.     int i;
  845.     if (!chartfile(chart, starfile)) die("open fail on %s", starfile);
  846.     chartfile(chart, planetfile);
  847.     chartfile(chart, messfile);
  848.     for (i = 0; i < nufiles; i++)
  849.     {
  850.     if (!chartfile(chart,userfile[i])) die("open fail on %s", userfile[i]);
  851.     }
  852.     }
  853.  
  854. chartfile(chart, filename)
  855.     map chart;
  856.     char *filename;
  857.     {
  858. #define READMODE "r"
  859. #define OPENFAIL 0
  860.     FILE *sfile;
  861.     if ((sfile = fopen(filename, READMODE)) == OPENFAIL) return(0);
  862.     chartobjects(chart, sfile);
  863.     fclose(sfile);
  864.     return(1);
  865.     }
  866.  
  867. chartobjects(chart, file)
  868.     map chart;
  869.     FILE *file;
  870.     {
  871.     float lat, lon, mag;
  872.     char code[1], subcode[1], label[100], name [100], color [3], *ptr;
  873.     int xloc, yloc, staronly, smallflag, vecmode, gkflag;
  874.  
  875.     for(;;)
  876.     {
  877.     if (readstar(file,&lat,&lon,&mag,code,subcode,color,label,name)) break;
  878.     if ((mag > chart->maglim) && (code[0] == 'S')) break;
  879.     if ((chart->west < 0.0) && (lon>180.0)) lon -= 360.0;
  880.     if ((chart->east > 360.0) && (lon<180.0)) lon += 360.0;
  881.     if ( ( (lon >= chart->west) && (lon <= chart->east) &&
  882.            (lat >= chart->south) && (lat <= chart->north) &&
  883.            (mag <= chart->maglim) )
  884.         || (code[0] == 'V') )    /* no spatial preclip on vector data */
  885.         {
  886.         xform(chart, lat, lon, &xloc, &yloc);
  887.         smallflag = vecmode = staronly = gkflag = 0;
  888.         switch(code[0])
  889.         {
  890.     case 'S':    pdrawStar(xloc,yloc,(int)(mag+0.5),subcode[0],color);
  891.         staronly = 1;
  892.         break;
  893.     case 'P':    pdrawPlan(xloc, yloc,(int)(mag+0.5),subcode[0],color);
  894.         break;
  895.     case 'N':    pdrawNebu(xloc, yloc,(int)(mag+0.5),subcode[0],color);
  896.         break;
  897.     case 'G':    pdrawGalx(xloc, yloc,(int)(mag+0.5),subcode[0],color);
  898.         break;
  899.     case 'C':    pdrawClus(xloc, yloc,(int)(mag+0.5),subcode[0],color);
  900.         break;
  901.     case 'I':    break;        /* invisible */
  902.     case 'V':    vecmode = 1;    /* vector: check subcodes */
  903.         if (subcode[0] == 'M') /* move */
  904.             {
  905.             olat = lat;
  906.             olon = lon;
  907.             }
  908.         else            /* draw */
  909.             {
  910.             float lat1, lon1, lat2, lon2;
  911.             if (clip(chart->north, chart->south, chart->west,
  912.                 chart->east, olon, olat, lon, lat,
  913.                 &lon1, &lat1, &lon2, &lat2))
  914.             {
  915.             xform(chart, lat1, lon1, &xloc, &yloc);
  916.             pvecmove(xloc, yloc);
  917.             xform(chart, lat2, lon2, &xloc, &yloc);
  918.             switch (subcode[0])
  919.                 {
  920.         case 'D':   pvecdrawdot(xloc, yloc); break;
  921.         case 'H':   pvecdrawhyph(xloc,yloc); break;
  922.         case 'S':   /* solid */
  923.         default:    pvecdraw(xloc, yloc); break;
  924.                 }
  925.             }
  926.             olat = lat;
  927.             olon = lon;
  928.             }
  929.         break;
  930.         }
  931. /*
  932.  * pick up object name or label if (star<limit), (nonstar), and (not vector)
  933.  */
  934.         if (((mag < chart->lbllim) || !staronly) && !vecmode)
  935.         {
  936.         ptr = NULL;
  937. /*
  938.  * if star is too "dark", mask off any proper name, so only label can appear.
  939.  */
  940.         if (staronly && (mag > chart->gklim)) *name = '\0';
  941. /*
  942.  * choose any proper name in favor of label
  943.  */
  944.         if (*name != '\0') ptr = name;
  945.         else if (*label != '\0')
  946.             {
  947.             ptr = label;
  948.             {
  949.             if (staronly)    /* star: Gk char(s) or Roman digits */
  950.                 {
  951.                 smallflag = 1;
  952.                 ptr[2] = '\0'; /* snuff the IAU designation */
  953.                 if(!isdigit(ptr[0]))
  954.                     {        /* is Bayer (Greek) */
  955.                     gkflag = 1;
  956.                     if (ptr[1] == ' ') ptr[1] = '\0';
  957.                     }
  958.                 }
  959.             }
  960.             }
  961.         if  (ptr != NULL)
  962.             {
  963.             pvecsize( smallflag ? FSIZESML : FSIZELRG);
  964. /*
  965.  * vecsyms* --
  966.  * some x offset present to avoid overstriking corresponding object. Note
  967.  * that some bias is already precent (obj is center-align, text is left align)
  968.  */
  969.             if (gkflag) pvecsymsgk(xloc+10, yloc, ptr);
  970.             else pvecsyms(xloc+10, yloc, ptr);
  971.             }
  972.         }
  973.         }
  974.     }
  975.     }
  976.  
  977. /*
  978.  * Chart Construction
  979.  */
  980.  
  981. chartbackground(chart)
  982.     map chart;
  983.     {
  984.     chartoutline(chart);
  985.     chartgrid(chart);
  986.     }
  987.  
  988. chartgrid(chart)
  989.     map chart;
  990.     {
  991.     charthgrid(chart, 15.0, 18);
  992.     charthgrid(chart, 5.0, 12);
  993.     charthgrid(chart, 1.0, 6);
  994.     chartvgrid(chart, 10.0, 18);
  995.     chartvgrid(chart, 5.0 , 12);
  996.     chartvgrid(chart, 1.0, 6);
  997.     }
  998.  
  999. chartoutline(chart)
  1000.     map chart;
  1001.     {
  1002.     float start, inc;
  1003.     int xloc, xloc2, yloc, yloc2, div, i;
  1004.  
  1005.     xform(chart, chart->south, chart->west, &xloc,  &yloc);
  1006.     xform(chart, chart->south, chart->east, &xloc2, &yloc2);
  1007.     pvecmovedraw(xloc, yloc, xloc2, yloc2);
  1008.     xform(chart, chart->north, chart->west, &xloc,  &yloc);
  1009.     xform(chart, chart->north, chart->east, &xloc2, &yloc2);
  1010.     pvecmovedraw(xloc, yloc, xloc2, yloc2);
  1011.  
  1012.     inc = (chart->north - chart->south);
  1013.     div = (int)(inc);
  1014.     if (div < 1) div = 1;
  1015.     inc /= div;
  1016.     start = chart->south;
  1017.     xform(chart, start, chart->west, &xloc, &yloc);
  1018.     pvecmove(xloc, yloc);
  1019.     for (i=0; i < div; i++)
  1020.     {
  1021.     start += inc;
  1022.     xform(chart, start, chart->west, &xloc, &yloc);
  1023.     pvecdraw(xloc, yloc);
  1024.     }
  1025.     start = chart->south;
  1026.     xform(chart, start, chart->east, &xloc, &yloc);
  1027.     pvecmove(xloc, yloc);
  1028.     for (i=0; i < div; i++)
  1029.     {
  1030.     start += inc;
  1031.     xform(chart, start, chart->east, &xloc, &yloc);
  1032.     pvecdraw(xloc, yloc);
  1033.     }
  1034.     }
  1035.  
  1036. rastr(str, ras)
  1037.     char *str;
  1038.     float ras;
  1039.     {
  1040.     int hrs, min;
  1041.     if (ras <   0.0) ras += 360.0;
  1042.     if (ras > 360.0) ras -= 360.0;
  1043.     hrs = (int)(ras/15.0);
  1044.     min = (int)((ras - hrs * 15.0) * 4.0);
  1045.     sprintf(str, "%2dh", hrs);
  1046.     if (min) sprintf(str, "%s%02dm", str, min);
  1047.     }
  1048.  
  1049. declstr(str, dl)
  1050.     char *str;
  1051.     float dl;
  1052.     {
  1053.     int deg, min;
  1054.     if (dl == 0.0) sprintf(str, "%s", " ");
  1055.     else if (dl > 0.0) sprintf(str, "%s", "+");
  1056.     else
  1057.     {
  1058.     sprintf(str, "%s", "-");
  1059.     dl = -dl;
  1060.     }
  1061.     deg = (int)(dl);
  1062.     min = (int)((dl - deg) * 60.0);
  1063.     sprintf(str, "%s%02dd", str, deg);
  1064.     if (min) sprintf(str, "%s%02dm", str, min);
  1065.     }
  1066.  
  1067. charthgrid(chart, inc, hgt)
  1068.     map chart;
  1069.     float inc;
  1070.     {
  1071. #define HTICKLIM 2
  1072. #define HTEXTLIM 80
  1073.     float start, stop, ras;
  1074.     int xloc, xloc2, yloc, xloc3, yloc3;
  1075.     start = modup(chart->west, inc);
  1076.     stop = moddown(chart->east, inc);
  1077.     xform(chart, chart->south, start, &xloc, &yloc);
  1078.     xform(chart, chart->south, start+inc, &xloc2, &yloc);
  1079.     if (xloc - xloc2 > HTICKLIM)
  1080.     for (ras = start; ras <= stop; ras += inc)
  1081.         {
  1082.         xform(chart, chart->south, ras, &xloc3, &yloc3);
  1083.         pvecmovedraw(xloc3, yloc3-hgt, xloc3, yloc3);
  1084.         if (xloc - xloc2 > HTEXTLIM)
  1085.         {
  1086.         char tstr[20];
  1087.         rastr(tstr, ras);
  1088.         pvecsize(10);
  1089.         pvecsyms(xloc3+2, yloc-17, tstr);
  1090.         }
  1091.         }
  1092.     }
  1093.  
  1094. chartvgrid(chart, inc, wid)
  1095.     map chart;
  1096.     float inc;
  1097.     {
  1098. #define VTICKLIM 2
  1099. #define VTEXTLIM 20
  1100.     float start, stop, dl;
  1101.     int xloc, yloc, yloc2, xloc3, yloc3;
  1102.     start = modup(chart->south, inc);
  1103.     stop = moddown(chart->north, inc);
  1104.     xform(chart, start, chart->west, &xloc, &yloc);
  1105.     xform(chart, start+inc, chart->west, &xloc, &yloc2);
  1106.     if (yloc2 - yloc > VTICKLIM)
  1107.     {
  1108.     for (dl = start; dl <= stop; dl += inc)
  1109.         {
  1110.         xform(chart, dl, chart->west, &xloc3, &yloc3);
  1111.         pvecmovedraw(xloc3, yloc3, xloc3+wid, yloc3);
  1112.         if (yloc2 - yloc > VTEXTLIM)
  1113.         {
  1114.         char tstr[20];
  1115.         declstr(tstr, dl);
  1116.         pvecsize(10);
  1117.         pvecsyms(xloc3+24, yloc3, tstr);
  1118.         }
  1119.         }
  1120.     }
  1121.     }
  1122.  
  1123. /*
  1124.  * General Utilities
  1125.  */
  1126.  
  1127. float max(a, b)
  1128.     float a, b;
  1129.     {
  1130.     if (a>b) return(a);
  1131.     return(b);
  1132.     }
  1133.  
  1134. float modup(a, b)
  1135.     float a, b;
  1136.     {
  1137.     float new;
  1138.     new = ((float)((int)(a/b))*b);
  1139.     if (new >= a) return(new);
  1140.     return(new += b);
  1141.     }
  1142.  
  1143. float moddown(a, b)
  1144.     float a, b;
  1145.     {
  1146.     float new;
  1147.     new = ((float)((int)(a/b))*b);
  1148.     if (new <= a) return(new);
  1149.     return (new -= b);
  1150.     }
  1151.  
  1152. die(a,b)
  1153.     char *a, *b;
  1154.     {
  1155.     fprintf(stderr,"%s: ", progname);
  1156.     fprintf(stderr,a,b);
  1157.     fprintf(stderr,"\n");
  1158.     exit(1);
  1159.     }
  1160.  
  1161. #define LINELEN 80
  1162. static char legend[LINELEN];
  1163.  
  1164. findconst(tag)
  1165. char *tag;
  1166.      {
  1167. /*
  1168.  * lookup "con.locs" for a matching tag, and then substitute initial values
  1169.  * for ra, decl, scale, and label. File layout follows:
  1170.  *
  1171.  * com  13    25   10   Coma Bereneces
  1172.  * cor  15.45 28   10   Corona Borealis
  1173.  * 0....+....1....+....2....+....3
  1174.  */
  1175.     char *newline;
  1176.     FILE *cfile;
  1177.     int taglen;
  1178.     char cbuf[LINELEN+1];
  1179.  
  1180.     if ((cfile = fopen(constfile, "r")) == NULL)
  1181.     die("open fail on %s", constfile);
  1182.     taglen = strlen(tag);
  1183.     if ((taglen < 3) || (taglen > 4))
  1184.     die("constellation name must be three or four characters");
  1185.     for (;;)
  1186.     {
  1187.     fgets(cbuf, LINELEN, cfile);
  1188.     if (ferror(cfile)) die("read error in %s", constfile);
  1189.     if (feof(cfile)) break;
  1190.     if (strncmp(tag, cbuf, taglen) == 0)    /* FOUND */
  1191.         {    
  1192.         if (4!=sscanf(cbuf,"%*5s%f%f%f %[^\n]", &ra, &de, &sc, legend))
  1193.         die("bogus line in constellation file: %s", cbuf);
  1194.         ra    = ftod(ra);
  1195.         de    = ftod(de);
  1196.         if ((newline=index(legend, '\n')) != 0) *newline = '\0';
  1197.         title = legend;
  1198.         return;
  1199.         }
  1200.     }
  1201.     die("Constellation '%s' not found", tag);
  1202.     }
  1203.  
  1204. /*
  1205.  * intercept vector and text functions
  1206.  * (used for omission of detail, but generally useful for clipping, etc.)
  1207.  */
  1208.  
  1209. pvecsize(points)
  1210.     int points;
  1211.     {
  1212.     vecsize(points);
  1213.     }
  1214.  
  1215. pvecmove(x, y)
  1216.     {
  1217.     vecmove(x, y);
  1218.     }
  1219.  
  1220. pvecdrawdot(x, y)
  1221.     {
  1222.     if (objdetail) vecdrawdot(x, y);
  1223.     }
  1224.  
  1225. pvecdrawhyph(x, y)
  1226.     {
  1227.     if (objdetail) vecdrawhyph(x, y);
  1228.     }
  1229.  
  1230. pvecdraw(x, y)
  1231.     {
  1232.     if (objdetail) vecdraw(x, y);
  1233.     }
  1234.  
  1235. pvecsyms(x, y, s)
  1236.     char *s;
  1237.     {
  1238.     if (annodetail) vecsyms(x, y, s);
  1239.     }
  1240.  
  1241. pvecmovedraw(x, y, x2, y2)
  1242.     {
  1243.     if (objdetail) vecmovedraw(x, y, x2, y2);
  1244.     }
  1245.  
  1246. pdrawPlan(x, y, mag, type, color)
  1247.     char type, *color;
  1248.     {
  1249.     if (objdetail) drawPlan(x, y, mag, type, color);
  1250.     }
  1251.  
  1252. pdrawStar(x, y, mag, type, color)
  1253.     char type, *color;
  1254.     {
  1255.     if (objdetail) drawStar(x, y, mag, type, color);
  1256.     }
  1257.  
  1258. pdrawGalx(x, y, mag, type, color)
  1259.     char type, *color;
  1260.     {
  1261.     if (objdetail) drawGalx(x, y, mag, type, color);
  1262.     }
  1263.  
  1264. pdrawNebu(x, y, mag, type, color)
  1265.     char type, *color;
  1266.     {
  1267.     if (objdetail) drawNebu(x, y, mag, type, color);
  1268.     }
  1269.  
  1270. pdrawClus(x, y, mag, type, color)
  1271.     char type, *color;
  1272.     {
  1273.     if (objdetail) drawClus(x, y, mag, type, color);
  1274.     }
  1275.  
  1276. pvecsymsgk(str, x, y)
  1277.     char *str;
  1278.     {
  1279.     if (annodetail) vecsymsgk(str, x, y);
  1280.     }
  1281.  
  1282. /*
  1283.  * clipping extentions (awpaeth@watcgl)
  1284.  */
  1285.  
  1286. #define TOPFLAG 8
  1287. #define BOTTOMFLAG 4
  1288. #define LEFTFLAG 2
  1289. #define RIGHTFLAG 1
  1290.  
  1291. int clip(top, bottom, left, right, ix1, iy1, ix2, iy2, ox1, oy1, ox2, oy2)
  1292.     float top, bottom, left, right, ix1, iy1, ix2, iy2, *ox1, *oy1, *ox2,*oy2;
  1293.     {
  1294.     int c, c1, c2;
  1295.     float x, y;
  1296.  
  1297.     c1 = c2 = 0;
  1298.     if (ix1 < left) c1 |= LEFTFLAG; else if (ix1 > right) c1 |= RIGHTFLAG;
  1299.     if (iy1 < bottom) c1 |= BOTTOMFLAG; else if (iy1 > top) c1 |= TOPFLAG;
  1300.     if (ix2 < left) c2 |= LEFTFLAG; else if (ix2 > right) c2 |= RIGHTFLAG;
  1301.     if (iy2 < bottom) c2 |= BOTTOMFLAG; else if (iy2 > top) c2 |= TOPFLAG;
  1302.  
  1303.     while (c1 || c2)
  1304.     {
  1305.     if (c1 & c2) return(0);    /* bitwise AND, not statement AND */
  1306.     c = c1 ? c1 : c2;
  1307.     
  1308.     if (c & LEFTFLAG)
  1309.         y = iy1 + (iy2 - iy1) * ( (x = left) - ix1) / (ix2 - ix1);
  1310.     else if (c & RIGHTFLAG)
  1311.         y = iy1 + (iy2 - iy1) * ( (x = right) - ix1) / (ix2 - ix1);
  1312.     else if (c & TOPFLAG)    
  1313.         x = ix1 + (ix2 - ix1) * ( (y = top) - iy1) / (iy2 - iy1);
  1314.     else if (c & BOTTOMFLAG)    
  1315.         x = ix1 + (ix2 - ix1) * ( (y = bottom) - iy1) / (iy2 - iy1);
  1316.     
  1317.     if (c == c1)
  1318.         {
  1319.         ix1 = x;
  1320.         iy1 = y;
  1321.         c1 = 0;
  1322.         if (x < left) c1 |= LEFTFLAG; else if (x > right) c1 |= RIGHTFLAG;
  1323.         if (y < bottom) c1 |= BOTTOMFLAG; else if (y > top) c1 |= TOPFLAG;
  1324.         }
  1325.     else
  1326.         {
  1327.         ix2 = x;
  1328.         iy2 = y;
  1329.         c2 = 0;
  1330.         if (x < left) c2 |= LEFTFLAG; else if (x > right) c2 |= RIGHTFLAG;
  1331.         if (y < bottom) c2 |= BOTTOMFLAG; else if (y > top) c2 |= TOPFLAG;
  1332.         }
  1333.     }
  1334. /*  if ((ix1 == ix2) && (iy1 == iy2)) return(0); */    /* no motion */
  1335.     *ox1 = ix1;
  1336.     *oy1 = iy1;
  1337.     *ox2 = ix2;
  1338.     *oy2 = iy2;
  1339.     return(1);
  1340.     }
  1341.  
  1342. /*
  1343.  !--------------------------------------------------------------------------
  1344.  ! Future Development
  1345.  !
  1346.  ! Here is my "wish" list of items not added in this version (#2). I have
  1347.  ! intentionally included it here with the source code in an attempt to direct
  1348.  ! the course of further software development.
  1349.  !
  1350.  ! It is strongly suggested that all software extentions which will be re-
  1351.  ! posted to the general public be first forwarded to the current developer
  1352.  ! (presently the author) in an effort to avoid a multiplicity of dissimilar,
  1353.  ! but "cannonical" versions.
  1354.  !
  1355.  ! It is hoped that this will simplify the task of coordinating the eventual
  1356.  ! reintegration of new features created by such a large software community.
  1357.  ! Wishes are listed in rough order of simplicity and evolution.
  1358.  !
  1359.  !
  1360.  ! Software:
  1361.  !
  1362.  ! [0] add glyphs for double stars/variable stars + Greek on bitmap devices.
  1363.  ! [1] write better PostScript macros.
  1364.  !**partially done
  1365.  ! [2] integrate a "boundary.star" to draw constellation boundaries.
  1366.  ! [3] rewrite "moonphase" to add ra/decl information, merge into "planet.c".
  1367.  ! [4] break yale.star into constellation files (and remove "cons" field).
  1368.  ! [5] write "orbit.c" for asteroid overlays.
  1369.  ! [6] add a polar plot facility (round window?) for high declinations
  1370.  !**two previous attempts - success will be met when the output includes
  1371.  !**both proper frame boundaries and tick marks, and when the underlying
  1372.  !**code uses (and sensibly extends) the functions "xform" and chartparms, etc.
  1373.  ! [7] rework planet.star to give planet tracks for a range of dates.
  1374.  !**rumored to exist
  1375.  !
  1376.  ! Database additions:
  1377.  !
  1378.  ! [1'] convert a larger database (9th-10th mag) into Yale format.
  1379.  ! [2'] Milky Way isophots
  1380.  ! [3'] Ecliptic track (dotted line vectors)
  1381.  ! [4'] IAU Constellation boundaries (see [2])
  1382.  !
  1383.  ! (comments)
  1384.  !
  1385.  ! [0] Is best facilitated by revising the image compiler in "starimages.c".
  1386.  ! [1] Would allow nice glyphs for non-stellar objects, scaled continuously
  1387.  !     to the right size. The code already provides a "halo" feature when
  1388.  !     generating stars in bright to dim (large to small) order, following
  1389.  !     a common aesthetic convention in many atlases. Variable stars are
  1390.  !     given rings, bars pass through double stars, etc., but a more
  1391.  !     comprehensive set of glyphs would be nice.
  1392.  !
  1393.  !     Starchart now allows user specified generation of text and vectors,
  1394.  !     which are useful for giving planet tracks across a range of dates, plus
  1395.  !     constellation boundaries, and possibly shapes of moon phases ([2], [3]).
  1396.  ! [2] I have access to such a database from UC Santa Cruz, and will request
  1397.  !     it once proven software is available. It would then be reworked into
  1398.  !     the "yale.star" format, using the move/draw commands of.
  1399.  ! [3] Burgess' book "Celestial Basic" gives routines for this, but lacks the
  1400.  !     precision of the work by Meesus (see planet.man). Done correctly, one
  1401.  !     should be able to check for eclipses, transits and occultations (this
  1402.  !     will require that "moonphase" know the user's geocentric latitude and
  1403.  !     longitude, due to the libration of the moon owing to parallax). This
  1404.  !     advanced version would print the profile of the moon's limb, with
  1405.  !     terminator. The "basic" version would just give a planet symbol.
  1406.  ! [4] Break-down by constellation would be a simple conceptual organization.
  1407.  !     It is also helpful to users requiring detailed finder charts of select
  1408.  !     regions. At the very least, the thirteen files for ecliptic-based
  1409.  !     constellation (~the Zodiac) would be quite helpful. The three character
  1410.  !     constellation field in the "label" field of the newer (but still
  1411.  !     reduced) version of yale.star would then go.
  1412.  ! [5] I have already produced tables of Keplerian elements for asteroids
  1413.  !     to the 10th mag. I also have code to read the data and solve for various
  1414.  !     related values (e.g. eccentric anomoly from mean anomoly). Left are
  1415.  !     the routines to find earth's position, plus the spherical trig needed
  1416.  !     to convert this into Ra and Decl. This would best be integrated into
  1417.  !     "planet.c", which already does the latter. Interested parties should
  1418.  !     e-mail me for the files "orbit.c" and "asteroids.el".
  1419.  ! [6] xcen and ycen would be ignored, and scale would give the limit of
  1420.  !     declination (90.0-scale). Provisions to choose which pole needed, too.
  1421.  !     I believe stereographic projection would be the best, being both
  1422.  !     conformal and preserving of circles (as circles of new radii).
  1423.  ! [7] A complete rework would probably also place moon and asteroid calcs
  1424.  !     here, in addition to generating "track" output records.
  1425.  !
  1426.  ! [1'] Electronic databases to the 10th mag rumored to exist, containing on
  1427.  !    the order of 40000 stars. Don't ask me where to find them.
  1428.  ! [2'] No idea where to find
  1429.  ! [3'] Should not be too hard
  1430.  */
  1431. @//E*O*F starchart.c//
  1432. chmod u=r,g=r,o=r starchart.c
  1433.  
  1434. echo x - starchart.h
  1435. sed 's/^@//' > "starchart.h" <<'@//E*O*F starchart.h//'
  1436. typedef struct
  1437.     {
  1438.     float racen, dlcen, scale;
  1439.     float north, south, east, west;
  1440.     float maglim, lbllim, gklim;
  1441.     int wx, wy, ww, wh;
  1442.     float yscale;
  1443.     } mapblock, *map;
  1444.  
  1445. extern mapblock master, thumbnail, bigmaster;
  1446. @//E*O*F starchart.h//
  1447. chmod u=r,g=r,o=r starchart.h
  1448.  
  1449. echo x - stariris.c
  1450. sed 's/^@//' > "stariris.c" <<'@//E*O*F stariris.c//'
  1451. /*
  1452.  * IRIS driver for startchart.c mainline
  1453.  *
  1454.  * Tim Pointing, DCIEM
  1455.  * <decvax!utzoo!dciem!tim>
  1456.  */
  1457.  
  1458. #include <stdio.h>
  1459. #include <gl.h>
  1460. #include "starchart.h"
  1461.  
  1462. /*
  1463.  * Chart parameters (limiting magnitude and window x,y,w,h)
  1464.  */
  1465.  
  1466.  
  1467. mapblock master =    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  1468.              8.0, 3.0, 2.05, 20, 265, 880, 500, 0.0 };
  1469.  
  1470. mapblock bigmaster =    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  1471.              8.0, 3.0, 2.05, 20,  65, 880, 700, 0.0 };
  1472.  
  1473. mapblock thumbnail =    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  1474.              3.2, 1.0, 2.05, 420, 35, 480, 195, 0.0 };
  1475. /*
  1476.  * Generic Star Drawing Stuff
  1477.  */
  1478.  
  1479. vecopen()
  1480.    {
  1481.    keepaspect(1,1);
  1482.    getport();
  1483.    ortho(0., 1023., 0., 1023.);
  1484.    reshapeviewport();
  1485.    color(BLACK);
  1486.    clear();
  1487.    makeobj(1);
  1488.    color(BLACK);
  1489.    clear();
  1490.    color(WHITE);
  1491.    }
  1492.  
  1493. vecclose()
  1494.     {
  1495.     int x;
  1496.     closeobj(1);
  1497.     callobj(1);
  1498.     while(qread(&x))
  1499.     {
  1500.     ortho(0., 1023., 0., 1023.);
  1501.     reshapeviewport();
  1502.     callobj(1);
  1503.     }
  1504.     }
  1505.  
  1506. vecsize(points)
  1507.     int points;
  1508.     {
  1509.     }
  1510.  
  1511. vecmove(x, y)
  1512.     {
  1513.     move2i(x, y);
  1514.     }
  1515.  
  1516. vecdraw(x, y)
  1517.     {
  1518.     draw2i(x, y);
  1519.     }
  1520.  
  1521. vecdrawhyph(x, y)
  1522.     {
  1523.     draw2i(x, y);
  1524.     }
  1525.  
  1526. vecdrawdot(x, y)
  1527.     {
  1528.     draw2i(x, y);
  1529.     }
  1530.  
  1531. vecsyms(x, y, s)
  1532.     char *s;
  1533.     {
  1534.     color(WHITE);
  1535.     cmov2i(x, y-5); /* center character strings */
  1536.     charstr(s);
  1537.     color(WHITE);
  1538.     }
  1539.  
  1540. vecsymsgk(x, y, s)
  1541.     char *s;
  1542.     {
  1543.     vecsyms(x, y, s);
  1544.     }
  1545.  
  1546. vecmovedraw(x1, y1, x2, y2)
  1547.     {
  1548.     move2i(x1, y1);
  1549.     draw2i(x2, y2);
  1550.     }
  1551.  
  1552. drawlen(x, y, dx, dy, len)
  1553.     {
  1554.     vecmovedraw(x+dx, y+dy, x+dx+len, y+dy);
  1555.     }
  1556. /*
  1557.  * presently in conflict with stariamges.c
  1558.  */
  1559.  
  1560. #ifdef FIXED
  1561.  
  1562. drawPlan(x, y, mag, type, col)
  1563.     char type, *col;
  1564.     {
  1565.     color(YELLOW);
  1566.     switch(type)
  1567.     {
  1568.     case ('S'<<8)|('o'):    /* Sol */
  1569.         pnt2i(x, y);
  1570.         circi(x, y, 5);
  1571.         break;
  1572.     case ('M'<<8)|('e'):    /* Mercury */
  1573.         circi(x, y+1, 3);
  1574.         move2i(x, y-2);
  1575.         draw2i(x, y-5);
  1576.         move2i(x-2, y-4);
  1577.         draw2i(x+2, y-4);
  1578.         move2i(x-1, y+3);
  1579.         draw2i(x-2, y+5);
  1580.         move2i(x+1, y+3);
  1581.         draw2i(x+2, y+5);
  1582.         break;
  1583.     case ('V'<<8)|('e'):    /* Venus */
  1584.         circi(x, y+1, 3);
  1585.         move2i(x, y-2);
  1586.         draw2i(x, y-5);
  1587.         move2i(x-2, y-4);
  1588.         draw2i(x+2, y-4);
  1589.         break;
  1590.     case ('M'<<8)|('a'):    /* Mars */
  1591.         circi(x-2, y-2, 3);
  1592.         move2i(x, y);
  1593.         draw2i(x+3, y+3);
  1594.         draw2i(x+1, y+3);
  1595.         move2i(x+3, y+3);
  1596.         draw2i(x+3, y+1);
  1597.         break;
  1598.     case ('J'<<8)|('u'):    /* Jupiter */
  1599.         arci(x-2, y+2, 2, 3150, 1350);
  1600.         move2(x-.6, y+.6);
  1601.         draw2i(x-3, y-1);
  1602.         draw2i(x+1, y-1);
  1603.         move2i(x, y-2);
  1604.         draw2i(x, y+4);
  1605.         break;
  1606.     case ('S'<<8)|('a'):    /* Saturn */
  1607.         move2i(x-2, y+3);
  1608.         draw2i(x, y+3);
  1609.         move2i(x-1, y+3);
  1610.         draw2i(x-1, y-3);
  1611.         move2i(x-1, y+1);
  1612.         draw2i(x, y+1);
  1613.         draw2i(x+2, y);
  1614.         draw2i(x+2, y-1);
  1615.         draw2i(x+1, y-2);
  1616.         draw2i(x+1,y-3);
  1617.         break;
  1618.     case ('U'<<8)|('r'):    /* Uranus */
  1619.         circi(x, y-3, 3);
  1620.         pnt2i(x, y-3);
  1621.         move2i(x, y);
  1622.         draw2i(x, y+3);
  1623.         draw2i(x-1, y+2);
  1624.         move2i(x, y+3);
  1625.         draw2i(x+1, y+2);
  1626.         break;
  1627.     case ('N'<<8)|('e'):    /* Neptune */
  1628.         arci(x, y+3, 3, 1800, 3600);
  1629.         move2i(x, y+3);
  1630.         draw2i(x, y-6);
  1631.         move2i(x-2, y-5);
  1632.         draw2i(x+2, y-5);
  1633.         break;
  1634.     default:
  1635.         circi(x, y, 4);
  1636.         move2i(x, y-5);
  1637.         draw2i(x, y+5);
  1638.         move2i(x-5, y);
  1639.         draw2i(x+5, y);
  1640.         break;
  1641.     }
  1642.     color(WHITE);
  1643.     }
  1644.  
  1645. drawStar(x, y, mag, type, col)
  1646. char type, *col;
  1647.     {
  1648.     if (mag > 9) mag = 9;
  1649.     if (mag < 4)
  1650.     {
  1651.     color(WHITE);
  1652.     circfi(x, y, (int)((4-mag)/2));
  1653.     }
  1654.     else
  1655.     {
  1656.     color(31 - (mag-4)*3);
  1657.     pnt2i(x,y);
  1658.     }
  1659.     color(WHITE);
  1660.     }
  1661.  
  1662. drawNebu(x, y, mag, type, col)
  1663.     char type, *col;
  1664.     {
  1665.     }
  1666.  
  1667. drawGalx(x, y, mag, type, col)
  1668.     char type, *col;
  1669.     {
  1670.     }
  1671.  
  1672. drawClus(x, y, mag, type, col)
  1673.     char type, *col;
  1674.     {
  1675.     }
  1676.  
  1677. #endif
  1678. @//E*O*F stariris.c//
  1679. chmod u=r,g=r,o=r stariris.c
  1680.  
  1681. echo x - staruplot.c
  1682. sed 's/^@//' > "staruplot.c" <<'@//E*O*F staruplot.c//'
  1683. /*
  1684.  * Plotter Display driver for starchart.c mainline (UNIX Plot(5) style output)
  1685.  *
  1686.  * Sjoerd Mullender <sjoerd@cs.vu.nl>
  1687.  * Free University, Amsterdam
  1688.  */
  1689.  
  1690. #include <stdio.h>
  1691. #include <ctype.h>
  1692. #include "starchart.h"
  1693.  
  1694. #define SOLID        1
  1695. #define DOTTED        2
  1696. #define DASHED        3
  1697.  
  1698. static int mode = 0;
  1699.  
  1700. /*
  1701.  * Chart parameters (limiting magnitude and window x,y,w,h)
  1702.  */
  1703.  
  1704. mapblock thumbnail =    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  1705.             3.2, 1.0, 2.05, 420, 35, 480, 195, 0.0 };
  1706.  
  1707. mapblock master =    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  1708.             8.0, 3.0, 2.05, 20, 265, 880, 500, 0.0 };
  1709.  
  1710. mapblock bigmaster=    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  1711.             8.0, 3.0, 2.05, 20,  65, 880, 700, 0.0 };
  1712.  
  1713. vecopen()
  1714.     {
  1715.     openpl();
  1716.     space(0, 0, 1024, 768);
  1717.     erase();
  1718.     }
  1719.  
  1720. vecclose()
  1721.     {
  1722.     closepl();
  1723.     }
  1724.  
  1725. vecsize(points)
  1726.     int points;
  1727.     {
  1728.     }
  1729.  
  1730. vecmove(x, y)
  1731.     {
  1732.     move(x, y);
  1733.     }
  1734.  
  1735. vecdrawdot(x, y)
  1736.     {
  1737.     if (mode != DOTTED) linemod("dotted");
  1738.     mode = DOTTED;
  1739.     cont(x, y);
  1740.     }
  1741.  
  1742. vecdrawhyph(x, y)
  1743.     {
  1744.     if (mode != DASHED) linemod("shortdashed");
  1745.     mode = DASHED;
  1746.     cont(x, y);
  1747.     }
  1748.  
  1749. vecdraw(x, y)
  1750.     {
  1751.     if (mode != SOLID) linemod("solid");
  1752.     mode = SOLID;
  1753.     cont(x, y);
  1754.     }
  1755.  
  1756. vecsyms(x, y, s)
  1757.     char *s;
  1758.     {
  1759.     move(x, y);
  1760.     label(s);
  1761.     }
  1762.  
  1763. vecmovedraw(x1, y1, x2, y2)
  1764.     {
  1765.     vecmove(x1, y1);
  1766.     vecdraw(x2, y2);
  1767.     }
  1768.  
  1769. vecsymsgk(x, y, str)
  1770.     char *str;
  1771.     {
  1772.     vecsyms(x, y, str);
  1773.     }
  1774.  
  1775. drawlen(x, y, dx, dy, len)
  1776.     {
  1777.     move(x + dx, y + dy);
  1778.     cont(x + dx + len - 1, y + dy);
  1779.     }
  1780. @//E*O*F staruplot.c//
  1781. chmod u=r,g=r,o=r staruplot.c
  1782.  
  1783. exit 0
  1784.  
  1785.  
  1786.  
  1787.  
  1788.