rck@ihuxv.ATT.COM (R. C. Kukuk) (12/12/87)
The subject line says it all; the README says a little more. #!/bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile # README # allcons # starchart.1 # starchart.c # starchart.h # starvdi.c # tonet # This archive created: Fri Dec 11 15:52:40 1987 export PATH; PATH=/bin:$PATH if test -f 'Makefile' then echo shar: over-writing existing file "'Makefile'" fi cat << \SHAR_EOF > 'Makefile' # # Author: Petri Launiainen, Intrinsic Oy, Tampere, FINLAND (pl@intrin.FI) # # Based on the work of Alan W. Paeth # SHELL = /bin/sh # # put the Yale Star Catalog file path here: because the yale.star is # static (stars don't change so often :->), consider using some static # library path here - relative one is used for quick testing #STAR = "/usr/lib/starchart/yale.star" STAR = "/u/rck/Filecabinet/src/yale/yale.star" # similarly assign the Messier file path: #MESS = "/usr/lib/starchart/messier.star" MESS = "/u/rck/Filecabinet/src/yale/messier.star" CONST = "/u/rck/Filecabinet/src/yale/con.locs" # put the planet position file path here: it should be preferably # relative, thus allowing everyone to change planet positions according # to their interests. This file changes when the 'planet' program is # executed PLANET = "/u/rck/Filecabinet/src/yale/planet.star" # notice that starchart.o and planet are made dependent on Makefile, due # to the STAR, MESS, CONST and PLANET definitions here # put the installation directory here BINDIR = /usr/lbin CFLAGS = -O -DSTARFILE='$(STAR)' -DPLANETFILE='$(PLANET)' \ -DMESSFILE='$(MESS)' -DCONSTFILE='$(CONST)' LFLAGS = # star chart calculation routine file COBJ = starchart.o # default binary names: if you change these, change also the corresponding # make tags BINS = epoch moonphase planet startek stardsp starpic starhp \ starlaser starpost starvdi all: \ planet\ starhp\ stardsp\ starvdi\ startek\ starpic\ starpost\ starlaser\ epoch\ moonphase test: stardsp -c ori install: all strip $(BINS) mv $(BINS) $(BINDIR) starchart.o: starchart.c starchart.h Makefile moonphase: moonphase.o cc $(LFLAGS) moonphase.o -lm -o $@ epoch: epoch.o cc $(LFLAGS) epoch.o -lm -o $@ planet: planet.o Makefile cc $(LFLAGS) $(DEFINES) planet.o -lm -o $@ stardsp: $(COBJ) stardsp.o cc $(LFLAGS) $(COBJ) stardsp.o -lm -o $@ starvdi: $(COBJ) starvdi.o cc -G $(LFLAGS) starvdi.o $(COBJ) -lm -lcvdi -o $@ starpic: $(COBJ) starpic.o cc $(LFLAGS) $(COBJ) starpic.o -lm -o $@ startek: $(COBJ) startek.o starimages.o cc $(LFLAGS) $(COBJ) startek.o starimages.o -lm -o $@ starhp: $(COBJ) starhp.o starimages.o cc $(LFLAGS) $(COBJ) starhp.o starimages.o -lm -o $@ starlaser: $(COBJ) starlaser.o starimages.o cc $(LFLAGS) $(COBJ) starlaser.o starimages.o -lm -o $@ starpost: $(COBJ) starpost.o cc $(LFLAGS) $(COBJ) starpost.o -lm -o $@ make clean: rm -f *.o mlog core SHAR_EOF if test -f 'README' then echo shar: over-writing existing file "'README'" fi cat << \SHAR_EOF > 'README' This archive contains a starchart driver for the GSS-VDI implementation on the UNIX-PC. A modified starchart.c, starchart.h and Makefile are included. allcons is just a thrown in freebie, try it, you may like it! Starchart.c was also modified to print out all defined constellation tags, so a modified starchart.1 is also included. The star database is not included; I'm assuming you've already snarfed it off the network. BTW: If anyone knows how to get rid of that wasteful, thick border surrounding the VDI window, please let me know. That display area needs every pixel it can get. Ron Kukuk AT&T Bell Labs SHAR_EOF if test -f 'allcons' then echo shar: over-writing existing file "'allcons'" fi cat << \SHAR_EOF > 'allcons' NAPTIME=120 while read cons rest do case "$cons" in /*) continue ;; *) starvdi -c $cons & PID=$! sleep $NAPTIME kill $PID ;; esac done < con.locs SHAR_EOF if test -f 'starchart.1' then echo shar: over-writing existing file "'starchart.1'" fi cat << \SHAR_EOF > 'starchart.1' .TH starchart LOCAL 9/22/87 .ad b .SH NAME stardsp, starpic, startek, starpost, starhp, starlaser .br \- print astronomical star charts using Yale database. .SH SYNOPSIS \fBstar* RA DE [ scale title maglim lbllim ]\fR .br or .br \fB-r Ra -d Dl -s scale -t title -m maglim -l lbllim -f x.star\fR .br or .br \fB-c [ constellation | ? ] ... .SH DESCRIPTION These programs generate star charts based on data extracted from the Yale public domain star catalog. Output is to the terminal .RB (stardsp), Unix PIC file format .RB (starpic), Tektronix vector format .RB (startek), PostScript format .RB (starpost), Hewlett-Packard terminal vector format .RB (starhp) or in Hewlett-Packard Laserjet printer format .RB (starlaser). .PP Star data is optionally overlayed with other cosmic objects, such as planets. If limiting magnitudes are properly set and the Messier database is available, Messier objects and some NGC objects are also printed. .PP The starchart center is specified by two parameters: Right Ascension [0.00 to 24.00 hours] and Declination [-90.00 to +90.00 degrees]. An optional third parameter defines the N/S range of the output window, in degrees of declination. Digits after decimal point are taken as minutes: object positions can therefore be taken directly from a star catalog. .PP An optional fourth parameter gives a title. This conforms to the 'old' Yale star chart format. Two new parameters can be added after title, defining the magnitude limit and label printing magnitude limit. These are discussed below. All parameters can be given by using options, which offers more flexibility. Parameters are: .TP .B \-r Right ascension. .TP .B \-d Declination. .TP .B \-s Scale. .TP .B \-t Title. All these work as described above. New options are: .TP .B \-m Star limiting magnitude. This sets limits on the faintest stars displayed on the "master" view. Default limits are device driver dependent (more below). The "thumbnail" finder view is set to a related limit. .TP .B \-l Label limiting magnitude. The new Yale database contains both a small set of familiar names (for stars and special objects), plus an extensive list of labels (Greek Bayer letter or Flamsteed numbers). Star names (including planet names) always print for this small set. To avoid clutter, the labels may be omitted below a cut-off magnitude by specifying this value. .TP .B \-c A three or four character mnemonic follows, which is a search string for a matching line-item entry in the file \fBcon.locs\fP. If found, then the initial values for Ra, Decl, Scale and Title are taken from that file. An option of '?' prints the current set of constellation mnemonics. Because the command line is parsed from left to right, subsequent switches might change the scale, title, or otherwise fine-tune the new defaults. .TP .B \-f A file may be given containing ephemerides in the .star format, which will overlay the output. This is also useful for generating constellation boundaries, Milky Way isophots, and planet or satellite tracks. (The .star format additionally includes records for vector and text annotation). .PP The present implementations draw two viewports: a ``master'' chart plus a ``thumbnail'' overview with low limiting magnitude. Their location and the limiting magnitude is specified by records in the device driver, allowing the chart layout be tuned on a per-device basis. The output is annotated with viewport boundaries, a legend and axis labels. .PP Sanson's sinusoidal projection is used to map coordinates. This projection preserves both area and linearity in Declination (y axis). It gives good conformality (angle correctness) near the equator, so it is useful along the Ecliptic. Lines of RA converge at the poles (unlike cylindrical projections), though Cassiopeia and the Dipper reproduce well. .SH EXAMPLES .nf # Sagittarius: a nice bunch of Messier objects. starpost -c sgr -t "(Sagittarius 31 Oct 87)" >sag.ps .sp # Orion: the belt lies near 5h40m in RA, just below the CE. stardsp 5.32 -5 12 "Trapezium (Orion)" 8 5 | more .fi .SH FILES .nf .ta 2.6i \fByale.star\fP stellar information (mandatory) \fBmessier.star\fP Messier objects (optional) \fBplanet.star\fP Planets (optional) \fBcon.locs\fP default mnemonic locations .fi .br .sp These default paths can be easily changed in the Makefile. .SH BUGS No testing for bogus ranges and scales which may wrap the poles. The present implementation expects .B yale.star sorted by decreasing magnitude so that output is sequential, and then cuts off below a limiting magnitude. For more detailed charts spatial sorting is more appropriate. .PP If <minutes> part of the parameters is greater than 59 it is silently truncated to 59. .PP All .star file coordinates are for epoch E2000.0. The Messier objects in \fBmessier.star\fP were taken from precessed E1975.0 data. The additional NGC objects were taken from data in the star atlas by \fINorton\fP and precessed from E1950.0. Rough guesses on visual magnitude were made. .SH AUTHOR/EDITOR Alan Paeth, University of Waterloo (AWPaeth@watCGL) .SH CONTRIBUTORS Petri Launiainen (pl@intrin.FI) .br Jyrki Yli-Nokari (jty@intrin.FI) .br Robert Tidd (inp@VIOLET.BERKELEY.EDU) SHAR_EOF if test -f 'starchart.c' then echo shar: over-writing existing file "'starchart.c'" fi cat << \SHAR_EOF > 'starchart.c' /* * starchart.c -- version 2, September 1987 * * (c) copyright 1987 by Alan Paeth (awpaeth@watcgl) */ /* ! Version 2 modification authors: ! ! [a] Petri Launiainen, pl@intrin.FI (with Jyrki Yli-Nokari, jty@intrin.FI) ! [b] Bob Tidd, inp@VIOLET.BERKELEY.EDU ! [c] Alan Paeth, awpaeth@watcgl ! [d] R. C. Kukuk ! ! Changes and Additions: ! !a [1] STARFILE, PLANETFILE, etc. path designations are now in the Makefile !ac [2] Fractional Ra and Decl values are now hh.mm and mm.ss (base 60) !a [3] Command syntax now allows flags as well as old style (arg placement) !ab [4] Extended Yale database (courtesy B. Tidd) also supported on input !bc [5] Greek+Flamsteed numbers now appear as a hardcopy annotation !bc [6] Constellation file finds ra,dl,scale from command line pattern !c [7] New symbols for Nebulae, Galaxies and Clusters added (based on [4]) !c [8] Double star indications added (provisions for variable stars) ([4]) !a [9] Limiting magnitude flags for stars and labels allowed !c [10] Legend column reformatted to contain additional symbols [4] !a [11] Internal symbol compiler created for raster glyph creation !c [12] add Yale records for "moveto"/"drawto" and text annotations !c [13] added -f file.star to add ephemeride data !d [14] Wrote driver for UNIX-PC version of GSS VDI. !d [15] Added -c ? to print set of constellation tags. ! ! Bug Fixes: ! !a [1] no more core dumps (on SysV) when given bad command line parameters !c [2] Negative RA indications now "wrap" to 24hrs, etc. !bc [3] Mag values *rounded* to nearest unit value (common Atlas convention) !c [4] Removed any device dependent subroutines (eg. getopt). !d [5] #Ifdef'ed sscanf() format in constellation read. !d [6] Renamed function "xform" to fix a VDI library symbol clash. ! ! Final integration by the original author [c]. ! Questions, suggestions, and fixes should be e-mailed to him. */ #include <stdio.h> #include <math.h> #ifdef BERZERK #include <strings.h> #endif #include <ctype.h> #include "starchart.h" /* * datasets are local, unless defined in Makefile */ #ifndef STARFILE #define STARFILE "./yale.star" #endif #ifndef PLANETFILE #define PLANETFILE "./planet.star" #endif #ifndef MESSFILE #define MESSFILE "./messier.star" #endif #ifndef CONSTFILE #define CONSTFILE "./con.locs" #endif #define DCOS(x) (cos((x)*3.14159265354/180.0)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define THUMBDIFF 2.5 /* thumbnail mag lim is brighter */ #define THUMBMAX 5.0 /* but no lower than this value */ #define THUMBRATIO 1.2 /* and scaled by this size (yet is already wider) */ #define THUMBDEG 10.0 /* but this is the floor on finder scale */ #define FSIZESML 8 /* point size for star designation */ #define FSIZELRG 10 /* point size for other object annotations */ double max(), modup(), moddown(); double ftod(), htod(), atof(); /* globals */ char *progname; /* program name for errors */ double ra, de, sc; /* global chart attributes */ char *title; char *userfile; /* potential .star file of user ephemerides */ /* the code */ main(argc, argv) int argc; char *argv[]; { double thumbscale; commandline(argc, argv); vecopen(); chartparms(&master, ra, de, sc); thumbscale = MAX(sc * THUMBRATIO, THUMBDEG); chartparms(&thumbnail, ra, de, thumbscale); thumbnail.maglim = MIN(THUMBMAX, master.maglim - THUMBDIFF); chartall(&master); chartall(&thumbnail); chartlegend(&master); vecclose(); exit(0); } commandline(argc, argv) char **argv; { int j; static char *usage = "\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 ... ]"; progname = argv[0]; title = NULL; ra = 0.0; de = 0.0; sc = 0.0; /* * check command line style */ if (argc == 1) die("No arguments - %s", usage); if ((argv[1][0] == '-') && isalpha(argv[1][1])) { /* * new style command line (using flags) */ for (j = 1; j < argc; j++) { if (argv[j][0] != '-') die("unknown argument - %s", argv[j]); switch (argv[j][1]) { case 'c': findconst(argv[++j]); break; case 'r': ra = htod(argv[++j]); break; case 'd': de = htod(argv[++j]); break; case 's': sc = atof(argv[++j]); break; case 'l': master.lbllim = (float)(atof(argv[++j])); break; case 'm': master.maglim = (float)(atof(argv[++j])); break; case 't': title = argv[++j]; break; case 'f': userfile = argv[++j]; break; case 'u': die("%s", usage); default: die("unknown switch - %s", argv[j]); } if (j == argc) die("trailing command line flag - %s", argv[j-1]); } } else { /* * old style command line (position dependent) */ switch (argc) { case 7: master.maglim = (float)(atof(argv[6])); case 6: master.lbllim = (float)(atof(argv[5])); case 5: title = argv[4]; case 4: sc = atof(argv[3]); case 3: de = htod(argv[2]); case 2: ra = htod(argv[1]); break; default: die("too many arguments - %s", usage); } } } double ftod(x) double x; { int full; full = x; return(full + (x - full) * 100.0 / 60.0); } double htod(s) char *s; { /* * htod(str) reads floating point strings of the form {+-}hh.{mm} thus * allowing for fractional values in base 60 (ie, degrees/minutes). */ #ifdef GOOBER double x, sign; int full, frac; char *t; t = s-1; while(*++t) { if ((*t == ' ') || (*t = '\t') || (*t == '\n')) break; if (((*t<'0') || (*t>'9') ) && (*t!='.') && (*t!='+') && (*t!='-')) die("non-digit in dd.mm style numeric argument: %s", s); } if (s == NULL) return 0.0; full = frac = 0; sign = 1.0; if (*s == '-') { sign = -1.0; s++; } else if (*s == '+') s++; while (*s && *s != '.') full = 10 * full + *s++ - '0'; if (*s++ == '.') { if (*s) frac = 10 * (*s++ - '0'); if (*s) frac += *s++ - '0'; if (frac > 59) frac = 59; } x = (double) full + ((double) frac) / 60.0; return sign * x; #endif return(ftod(atof(s))); } chartparms(chart, ras, decl, scl) double ras, decl, scl; map chart; { double adj, xscale; chart->racen = ras * 360.0 / 24.0; chart->dlcen = decl; chart->scale = scl; if (chart->scale == 0.0) chart->scale = 15.0; chart->north = chart->dlcen + chart->scale / 2.0; chart->south = chart->dlcen - chart->scale / 2.0; /* * xscale is other than chart->scale in order to widen the * horizontal viewing area, which otherwise shrinks near the * poles under Sanson's projection this happens in polar maps * which do not span the celestial equator */ adj = 1.0; if (chart->north * chart->south > 0.0) adj = max(DCOS(chart->north), DCOS(chart->south)); xscale = chart->scale / adj; chart->east = (chart->racen + xscale * chart->ww / chart->wh / 2.0); chart->west = (chart->racen - xscale * chart->ww / chart->wh / 2.0); chart->yscale = chart->wh / chart->scale; } chartlegend(chart) map chart; { char ras[2], dls[20], outstr[40]; if ( ! title) title = "LEGEND"; rastr(ras, chart->racen); declstr(dls, chart->dlcen); sprintf(outstr, "(%s,%s lim: %2.1f)", ras, dls, chart->maglim); vecsize(16); vecsyms(65, 220, title); vecsize(10); vecsyms(65, 185, outstr); vecsize(12); drawStar(65, 150, 0, 'S', NULL); vecsyms(95, 150, "<0.5"); if (chart->maglim >= 0.5) { vecsize(10); drawStar(230, 150, 1, 'S', NULL); vecsyms(260, 150, "<1.5"); } if (chart->maglim >= 1.5) { vecsize(9); drawStar(65, 125, 2, 'S', NULL); vecsyms(95, 125, "<2.5"); } if (chart->maglim >= 2.5) { vecsize(8); drawStar(230, 125, 3, 'S', NULL); vecsyms(260, 125, "<3.5"); } if (chart->maglim >= 3.5) { vecsize(7); drawStar(65, 100, 4, 'S', NULL); vecsyms(95, 100, "<4.5"); } if (chart->maglim > 4.5) { vecsize(6); drawStar(230, 100, 5, 'S', NULL); vecsyms(260, 100, ">4.5"); } vecsize(10); vecsyms(95, 75, "double"); drawStar(65, 75, 2, 'D', NULL); vecsize(10); vecsyms(260, 75, "variable"); drawStar(230, 75, 2, 'V', NULL); vecsize(10); vecsyms(95, 50, "planet"); drawPlan(65, 50, 1, 'S', NULL); vecsize(10); vecsyms(260, 50, "galaxy"); drawGalx(230, 50, 1, 'S', NULL); vecsize(10); vecsyms(95, 25, "nebula"); drawNebu(65, 25, 1, 'S', NULL); vecsize(10); vecsyms(260, 25, "cluster"); drawClus(230, 25, 1, 'S', NULL); } readstar(file, lat, lon, mag, code, subcode, color, label, name) FILE *file; double *lat, *lon, *mag; char *code, *subcode, *color, *label, *name; { #define LINELEN 80 char sbuf[LINELEN+1], *ptr; double rah, ram, ras, dld, dlm, dl, inten; int len, i; /* * file formats: * new * 064509-1643-99SDA1a CMASirius * 051432-0812015SDB8b ORIRigel * old * 064509-1643-146SSSirius * 051432-08120015SSRigel */ fgets(sbuf, LINELEN, file); if (feof(file)) return(1); /* * sscanf of floats is TOOO slow: * sscanf(sbuf, "%2f%2f%2f%c%2f%2f ... ); * use alternate: */ #define F2(i) ((double)((sbuf[i]-'0')*10+sbuf[i+1]-'0')) #define F3(i) ((double)((sbuf[i]-'0')*100+(sbuf[i+1]-'0')*10+sbuf[i+2]-'0')) #define F4(i) ((double)((sbuf[i]-'0')*1000+(sbuf[i+1]-'0')*100+(sbuf[i+2])-'0')*10+sbuf[i+3]-'0') rah = F2(0); ram = F2(2); ras = F2(4); dld = F2(7); dlm = F2(9); /* * common code */ #define DLDEGSEC 3600.0 #define DLMINSEC 60.0 #define RAHRSSEC 54000.0 #define RAMINSEC 900.0 #define RASECSEC 15.0 *lon = (RAHRSSEC * rah + RAMINSEC * ram + RASECSEC * ras) / DLDEGSEC; dl = (DLDEGSEC * dld + DLMINSEC * dlm) / DLDEGSEC; *lat = (sbuf[6] == '-') ? -dl : dl; if (isdigit(sbuf[14])) { /* * old reduced Yale catalog */ inten = F3(12); if (sbuf[11] == '0' || sbuf[11] == '+') *mag = inten / 100.0; else if (sbuf[11] == '-') *mag = -inten / 100.0; else *mag = F4(11); /* new feature for stars >= 10.0 mag */ if (sbuf[11] != 0) code[0] = sbuf[15]; subcode[0] = sbuf[16]; color[0] = '\0'; strcpy(color, " "); /* set unknowns to blanks */ label[0] = '\0'; name[0] = '\0'; strncat(name, &sbuf[17], strlen(&sbuf[17]) - 1); } else { /* * new reduced Yale catalog */ *mag = ((sbuf[11] == '-') ? -F2(12) : F3(11)) / 100.0; code[0] = sbuf[14]; /* let's get Sirius */ subcode[0] = sbuf[15]; color[0] = '\0'; label[0] = '\0'; name[0] = '\0'; switch (code[0]) { case 'C': case 'N': case 'G': /* * name vs label: * * A "name" is a common English term for a star or * cosmic object (eg Polaris, Pleiades). A label is * an official designation for such an object (eg * alpha-Ursa Minor, M45). For stars, labels are * taken from the two column Bayer/Flamsteed field * in the new reduced label format and the proper name * from the "name" field (the label field might also * include the three letter IAU constellation * designation, but at present these are ignored) * * For non-stellar objects, the Bayer and IAU fields * are typically blank (and always ignored), and the * "name" field consists of the designation followed * by an optional proper name, or perhaps just an * annotation, the latter flagged by a leading "," * and ignored by the software. For instance, the * entry "m45 Pleiades" forms a label "m45" and a name * "Pleiades", but the entry "m6 ,butterfly shape" * forms merely the label "m6". * * At the present, the charting software which is * supplied this data on a call to "readstar" will * print names in favor of labels. */ /* * extract Messier number and name */ strcpy(color, " "); ptr = &sbuf[23]; i = 0; while (isalnum(*ptr)) label[i++] = *ptr++; label[i] = '\0'; i = 0; while (*ptr == ' ') ptr++; while (*ptr != ',' && *ptr != '\n' && *ptr) name[i++] = *ptr++; name[i] = '\0'; break; default: /* * extract color, label and name */ strncat(color, &sbuf[16], 2); strncat(label, &sbuf[18], strlen(&sbuf[18]) - 1); if ((len = strlen(label)) > 5) { strncat(name, &label[5], len - 5); label[5] = '\0'; } } } return(0); } transform(chart, lat, lon, xloc, yloc) map chart; double lat, lon; int *xloc, *yloc; { /* * This is Sanson's Sinusoidal projection. Its properties: * (1) area preserving * (2) preserves linearity along y axis (declination/azimuth) */ *xloc = chart->wx + chart->ww / 2 + (chart->racen - lon) * chart->yscale * DCOS(lat); *yloc = chart->wy + (int)((lat - chart->south) * chart->yscale); } chartall(chart) map chart; { /* * we might "die" after drawing the borders, but we want * stars to overlay the border for imaging software which * may handle the bottom-up 2-1/2D order of printing correctly * (eg PostScript). */ chartoutline(chart); chartgrid(chart); if (!chartfile(chart, STARFILE)) die("open fail on %s", STARFILE); chartfile(chart, PLANETFILE); chartfile(chart, MESSFILE); if (userfile) { if (!chartfile(chart, userfile)) die("open fail on %s", userfile); } } chartfile(chart, filename) map chart; char *filename; { #define READMODE "r" #define OPENFAIL 0 FILE * sfile; if ((sfile = fopen(filename, READMODE)) == OPENFAIL) return(0); chartobjects(chart, sfile); fclose(sfile); return(1); } chartobjects(chart, file) map chart; FILE *file; { double lat, lon, mag; char code[1], subcode[1], label[100], name[100], color [3], *ptr; int xloc, yloc, staronly, smallflag, vecmode, gkflag, xcur, ycur; for ( ; ; ) { if (readstar(file, &lat, &lon, &mag, code, subcode, color, label, name)) break; if ((mag > chart->maglim) && (code[0] == 'S')) break; if ((chart->west < 0.0) && (lon > 180.0)) lon -= 360.0; if ((chart->east > 360.0) && (lon < 180.0)) lon += 360.0; if ((lon >= chart->west) && (lon <= chart->east) && (lat >= chart->south) && (lat <= chart->north) && (mag <= chart->maglim) ) { transform(chart, lat, lon, &xloc, &yloc); smallflag = vecmode = staronly = gkflag = 0; switch (code[0]) { case 'S': drawStar(xloc, yloc, (int)(mag + 0.5), subcode[0], color); staronly = 1; break; case 'P': drawPlan(xloc, yloc); break; case 'N': drawNebu(xloc, yloc); break; case 'G': drawGalx(xloc, yloc); break; case 'C': drawClus(xloc, yloc); break; case 'I': /* invisible */ break; case 'V': vecmode = 1; /* vector: check subcode */ switch (subcode[0]) { case 'M': vecmove(xloc, yloc); break; case 'D': vecdrawdot(xloc, yloc); break; case 'H': vecdrawhyph(xloc, yloc); break; case 'S': /* solid */ default: vecdraw(xloc, yloc); break; } break; } if (((mag < chart->lbllim) || ! staronly) && ! vecmode) { /* * pick up object name or label if * (star < limit), (nonstar), and (not vector) */ ptr = NULL; if (*name != '\0') { ptr = name; /* name > label */ } else if (*label != '\0') { ptr = label; if (staronly) { smallflag = 1; ptr[2] = '\0'; /* snuff the IAU designation */ if (islower(ptr[0]) || ptr[0] == 'E' || ptr[0] == 'O' || ptr[0] == '@' || ptr[0] == '%') { /* *Greek Bayer char(s) */ gkflag = 1; if (ptr[1] == ' ') ptr[1] = '\0'; } } } if (ptr != NULL) { vecsize(smallflag ? FSIZESML : FSIZELRG); /* * vecsyms* -- * some x offset present to avoid * overstriking corresponding object. * Note that some bias is already * precent (obj is center-align, * text is left align) */ if (gkflag) vecsymsgk(xloc + 10, yloc, ptr); else vecsyms(xloc + 10, yloc, ptr); } } } } } /* * Chart Construction */ chartgrid(chart) map chart; { charthgrid(chart, 15.0, 18); charthgrid(chart, 5.0, 12); charthgrid(chart, 1.0, 6); chartvgrid(chart, 10.0, 18); chartvgrid(chart, 5.0 , 12); chartvgrid(chart, 1.0, 6); } chartoutline(chart) map chart; { double start, inc; int xloc, xloc2, yloc, yloc2, div, i; transform(chart, chart->south, chart->west, &xloc, &yloc); transform(chart, chart->south, chart->east, &xloc2, &yloc2); vecmovedraw(xloc, yloc, xloc2, yloc2); transform(chart, chart->north, chart->west, &xloc, &yloc); transform(chart, chart->north, chart->east, &xloc2, &yloc2); vecmovedraw(xloc, yloc, xloc2, yloc2); inc = (chart->north - chart->south); div = (int) inc; if (div < 1) div = 1; inc /= div; start = chart->south; transform(chart, start, chart->west, &xloc, &yloc); vecmove(xloc, yloc); for (i = 0; i < div; i++) { start += inc; transform(chart, start, chart->west, &xloc, &yloc); vecdraw(xloc, yloc); } start = chart->south; transform(chart, start, chart->east, &xloc, &yloc); vecmove(xloc, yloc); for (i = 0; i < div; i++) { start += inc; transform(chart, start, chart->east, &xloc, &yloc); vecdraw(xloc, yloc); } } rastr(str, ras) char *str; double ras; { int hrs, min; if (ras < 0.0) ras += 360.0; if (ras > 360.0) ras -= 360.0; hrs = (int)(ras / 15.0); min = (int)((ras - hrs * 15.0) * 4.0); sprintf(str, "%dh", hrs); if (min) sprintf(str, "%s%02dm", str, min); } declstr(str, dl) char *str; double dl; { int deg, min; if (dl == 0.0) sprintf(str, "%s", " "); else if (dl > 0.0) sprintf(str, "%s", "+"); else { sprintf(str, "%s", "-"); dl = -dl; } /* * Watch out for the "pole wrap" syndrome. */ if (dl > 90.0) dl = 90. - (dl - 90.); deg = (int)(dl); min = (int)((dl - deg) * 60.0); sprintf(str, "%s%02dd", str, deg); if (min) sprintf(str, "%s%02dm", str, min); } charthgrid(chart, inc, hgt) map chart; double inc; { #define HTICKLIM 2 #define HTEXTLIM 80 double start, stop, ras; int xloc, xloc2, yloc, xloc3, yloc3; start = modup(chart->west, inc); stop = moddown(chart->east, inc); transform(chart, chart->south, start, &xloc, &yloc); transform(chart, chart->south, start + inc, &xloc2, &yloc); if (xloc - xloc2 > HTICKLIM) { for (ras = start; ras <= stop; ras += inc) { transform(chart, chart->south, ras, &xloc3, &yloc3); vecmovedraw(xloc3, yloc3 - hgt, xloc3, yloc3); if (xloc - xloc2 > HTEXTLIM) { char tstr[20]; rastr(tstr, ras); vecsize(10); vecsyms(xloc3 + 2, yloc - 17, tstr); } } } } chartvgrid(chart, inc, wid) map chart; double inc; { #define VTICKLIM 2 #define VTEXTLIM 20 double start, stop, dl; int xloc, yloc, yloc2, xloc3, yloc3; start = modup(chart->south, inc); stop = moddown(chart->north, inc); transform(chart, start, chart->west, &xloc, &yloc); transform(chart, start + inc, chart->west, &xloc, &yloc2); if (yloc2 - yloc > VTICKLIM) { for (dl = start; dl <= stop; dl += inc) { transform(chart, dl, chart->west, &xloc3, &yloc3); vecmovedraw(xloc3, yloc3, xloc3 + wid, yloc3); if (yloc2 - yloc > VTEXTLIM) { char tstr[20]; declstr(tstr, dl); vecsize(10); vecsyms(xloc3 + 24, yloc3, tstr); } } } } /* * General Utilities */ double max(a, b) double a, b; { if (a > b) return(a); return(b); } double modup(a, b) double a, b; { double new; new = ((double)((int)(a / b)) * b); if (new >= a) return(new); return(new += b); } double moddown(a, b) double a, b; { double new; new = ((double)((int)(a / b)) * b); if (new <= a) return(new); return (new -= b); } die(a, b) char *a, *b; { fprintf(stderr, "%s: ", progname); fprintf(stderr, a, b); fprintf(stderr, "\n"); exit(1); } static char legend[LINELEN]; findconst(tag) char *tag; { /* * lookup "con.locs" for a matching tag, and then substitute * initial values for ra, decl, scale, and label. * File layout follows: * * com 13 25 10 Coma Bereneces * cor 15.45 28 10 Corona Borealis * 0....+....1....+....2....+....3 */ char *newline; FILE *cfile; int taglen; char cbuf[LINELEN+1]; if ((cfile = fopen(CONSTFILE, "r")) == NULL) die("open fail on %s", CONSTFILE); /* * Print current tags if tag is "?". */ if ( ! strcmp(tag, "?")) { prttags(cfile); exit(0); } taglen = strlen(tag); if ((taglen < 3) || (taglen > 4)) die("constellation name must be three or four characters"); for (; ; ) { fgets(cbuf, LINELEN, cfile); if (ferror(cfile)) die("read error in %s", CONSTFILE); if (feof(cfile)) break; if (strncmp(tag, cbuf, taglen) == 0) { #ifdef BERZERK sscanf(&cbuf[taglen], "%f%f%f %[^\n]", &ra, &de, &sc, legend); #else sscanf(&cbuf[taglen], "%lf%lf%lf %[^\n]", &ra, &de, &sc, legend); #endif ra = ftod(ra); de = ftod(de); if ((newline = index(legend, '\n')) != 0) *newline = '\0'; title = legend; return; } } die("Constellation '%s' not found", tag); } /* * Print the constellation tags from con.locs. */ prttags(cfp) FILE *cfp; { int llen, lentmp; char inbuf[LINELEN], *cp1, *cp2; #define LINEMAX (LINELEN - 10) fprintf(stdout, "These are the constellation tags:\n "); llen = 3; cp1 = inbuf; /* * And print the tags. */ while (fgets(cp1, LINELEN, cfp)) { /* * Skip comments */ if (*cp1 == '/') continue; /* * Find the end of constellation tag. */ for (cp2 = cp1; ! isspace(*cp2); cp2++) ; *cp2 = '\0'; /* * Check for line overflow. */ if (llen + (lentmp = strlen(cp1) + 1) > LINEMAX) { llen = 3; fprintf(stdout, "\n "); } llen += lentmp; /* * Print it at last */ fprintf(stdout, " %s", cp1); } putchar('\n'); fclose(cfp); } /* ! Future Development ! ! Here is my "wish" list of items not added in this version (#2). I have ! intentionally included it here with the source code in an attempt to direct ! the course of further software development. ! ! It is hoped that this will simplify the task of coordinating the eventual ! reintegration of new features created by such a large software community. ! Wishes are listed in rough order of simplicity and evolution. ! ! Software: ! ! [0] add glyphs for double stars/variable stars + Greek on bitmap devices. ! [1] write better PostScript macros. ! [2] integrate a "boundary.star" to draw constellation boundaries. ! [3] rewrite "moonphase" to add ra/decl information, merge into "planet.c". ! [4] break yale.star into constellation files (and remove "cons" field). ! [5] write "orbit.c" for asteroid overlays. ! [6] add a polar plot facility (round window?) for high declinations ! [7] rework planet.star to give planet tracks for a range of dates. ! ! Database additions: ! ! [1'] convert a larger database (9th-10th mag) into Yale format. ! [2'] Milky Way isophots ! [3'] Ecliptic track (dotted line vectors) ! [4'] IAU Constellation boundaries (see [2]) ! ! (comments) ! ! [0] Is best facilitated by revising the image compiler in "starimages.c". ! [1] Would allow nice glyphs for non-stellar objects, scaled continuously ! to the right size. The code already provides a "halo" feature when ! generating stars in bright to dim (large to small) order, following ! a common aesthetic convention in many atlases. Variable stars are ! given rings, bars pass through double stars, etc., but a more ! comprehensive set of glyphs would be nice. ! ! Starchart now allows user specified generation of text and vectors, ! which are useful for giving planet tracks across a range of dates, plus ! constellation boundaries, and possibly shapes of moon phases ([2], [3]). ! [2] I have access to such a database from UC Santa Cruz, and will request ! it once proven software is available. It would then be reworked into ! the "yale.star" format, using the move/draw commands of. ! [3] Burgess' book "Celestial Basic" gives routines for this, but lacks the ! precision of the work by Meesus (see planet.man). Done correctly, one ! should be able to check for eclipses, transits and occultations (this ! will require that "moonphase" know the user's geocentric latitude and ! longitude, due to the libration of the moon owing to parallax). This ! advanced version would print the profile of the moon's limb, with ! terminator. The "basic" version would just give a planet symbol. ! [4] Break-down by constellation would be a simple conceptual organization. ! It is also helpful to users requiring detailed finder charts of select ! regions. At the very least, the thirteen files for ecliptic-based ! constellation (~the Zodiac) would be quite helpful. The three character ! constellation field in the "label" field of the newer (but still ! reduced) version of yale.star would then go. ! [5] I have already produced tables of Keplerian elements for asteroids ! to the 10th mag. I also have code to read the data and solve for various ! related values (e.g. eccentric anomoly from mean anomoly). Left are ! the routines to find earth's position, plus the spherical trig needed ! to convert this into Ra and Decl. This would best be integrated into ! "planet.c", which already does the latter. Interested parties should ! e-mail me for the files "orbit.c" and "asteroids.el". ! [6] xcen and ycen would be ignored, and scale would give the limit of ! declination (90.0-scale). Provisions to choose which pole needed, too. ! I believe stereographic projection would be the best, being both ! conformal and preserving of circles (as circles of new radii). ! [7] A complete rework would probably also place moon and asteroid calcs ! here, in addition to generating "track" output records. ! ! [1'] Electronic databases to the 10th mag rumored to exist, containing on ! the order of 40000 stars. Don't ask me where to find them. ! [2'] No idea where to find ! [3'] Should not be too hard */ SHAR_EOF if test -f 'starchart.h' then echo shar: over-writing existing file "'starchart.h'" fi cat << \SHAR_EOF > 'starchart.h' typedef struct { float racen, dlcen, scale; float north, south, east, west; float maglim, lbllim; int wx, wy, ww, wh; float yscale; } mapblock, *map; extern mapblock master, thumbnail; #ifndef BERZERK #define index strchr char *strchr(); #endif SHAR_EOF if test -f 'starvdi.c' then echo shar: over-writing existing file "'starvdi.c'" fi cat << \SHAR_EOF > 'starvdi.c' /* * Virtual Device Interface for UNIX-PC. */ #include <stdio.h> #include <ctype.h> #include "starchart.h" #define XMAX 32767 /* Max X on UNIX PC */ #define YMAX 17704 /* Max Y on UNIX PC */ #define SCALE 30 /* * Chart parameters (limiting magnitude and window x,y,w,h). * Display is assumed to be 554 (y) by 1024 (x) (17704/32767). */ mapblock thumbnail = { 0.0, 0.0, 0.0, /* racen, dlcen, scale */ 0.0, 0.0, 0.0, 0.0, /* north, south, east, west */ 3.0, 1.0, /* maglim, lbllim */ 20, 554/2, /* wx, wy origin (ll corner) */ (3*554)/5, 554/2, /* ww, wh */ 0.0 /* yscale */ }; mapblock master = { /* Ditto */ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.9, 4.0, 440, 48, 564, 524, 0.0 }; /* * Line types and fill directives. */ #define SOLID 1 #define DASHED 2 #define DOTTED 3 #define HOLLOW 0 #define HATCH 3 #define BLACK 0 #define WHITE 1 #define STORE 4 static short pixop = STORE; static short display; static short printer; static short disp_out[66]; static short prtr_out[66]; static short disp_in[19] = { 1, /* ndc index (equal axis ratios) */ 1, /* polyline line type */ WHITE, /* polyline color index */ 3, /* polymarker type */ WHITE, /* polymarker color index */ 1, /* graphics text font */ WHITE, /* graphics text color index */ SOLID, /* fill interior style */ 1, /* fill style index */ WHITE, /* fill color index */ 1, /* display prompts */ 'D', 'I', 'S', 'P', 'L', 'A', 'Y', ' ', /* device name */ }; static short prtr_in[19] = { 1, /* equal axis ratios */ 1, /* solid line type */ WHITE, /* line color index to use - white */ 3, /* marker type - star */ WHITE, /* marker color index - white */ 1, /* text font to use - normal */ WHITE, /* text color - white */ SOLID, /* fill interior style - hollow */ 1, /* fill style index */ WHITE, /* fill color index */ 1, /* send device messages to screen */ 'P', 'R', 'I', 'N', 'T', 'E', 'R', ' ' /* device name */ }; /* * initialize 7300 graphics window and VDI */ vecopen() { short d1, d2; /* * initialize VDI */ if (v_opnwk(disp_in, &display, disp_out) != 0) die("%s", "VDI initialization error"); /* * Set STORE (overwrite) mode for writing operations. */ if (vswr_mode(display, pixop) < 0) die("%s", "Overwrite setup error"); /* * Set text alignment, left justified, centered vertically. */ vst_alignment(display, (short) 0, (short) 1, &d1, &d2); } static textsize = 7; vecsize(points) int points; { textsize = points; } static short oldx, oldy; static short linetype = SOLID; vecmove(x, y) { oldx = x * SCALE; oldy = y * SCALE; } vecdrawdot(x, y) { linetype = DOTTED; vecdraw(x, y); linetype = SOLID; } vecdrawhyph(x, y) { linetype = DASHED; vecdraw(x, y); linetype = SOLID; } vecdraw(x, y) { short p1[2], p2[2]; p1[0] = oldx; p1[1] = oldy; p2[0] = x * SCALE; p2[1] = y * SCALE; oldx = x * SCALE; oldy = y * SCALE; draw_line(p1, p2); } vecsyms(x, y, s) char *s; { char c; vecmove(x, y); x *= SCALE; y *= SCALE; draw_text(x, y, s, textsize, 0); } vecmovedraw(x1, y1, x2, y2) { vecmove(x1, y1); vecdraw(x2, y2); } drawPlan(x, y) { draw2(x, y, 'P'); } drawStar(x, y, mag, type, color) char type, *color; { switch (mag) { case -1: draw0(x, y, type); break; case 0: draw0(x, y, type); break; case 1: draw1(x, y, type); break; case 2: draw2(x, y, type); break; case 3: draw3(x, y, type); break; case 4: draw4(x, y, type); break; default: draw5(x, y, type); break; } } #define STARSIZE (4*SCALE) draw0(x, y, type) { draw_disk(x, y, (8*STARSIZE)/5, type); } draw1(x, y, type) { draw_disk(x, y, (7*STARSIZE)/5, type); } draw2(x, y, type) { draw_disk(x, y, (6*STARSIZE)/5, type); } draw3(x, y, type) { draw_disk(x, y, (5*STARSIZE)/5, type); } draw4(x, y, type) { draw_disk(x, y, (short) 4, type); } draw5(x, y, type) { draw_disk(x, y, (short) 5, type); } drawGalx(x, y) { vecsyms(x, y, "@"); } drawNebu(x, y) { vecsyms(x, y, "~"); } drawClus(x, y) { vecsyms(x, y, "%"); } draw_disk(x, y, radius, type) short x, y; short radius, type; { short pp[4]; x *= SCALE; y *= SCALE; if (radius == 5) { /* Actually magnitude */ /* * Draw one pixel by drawing a very, very short * horizontal line. */ pp[0] = x; pp[1] = y; pp[2] = x + SCALE; pp[3] = y; v_pline(display, 2, pp); } else if (radius == 4) { /* Actually magnitude */ /* * Draw a three by three pixel box (centered). */ x -= SCALE; y -= SCALE; pp[0] = x; pp[1] = y; pp[2] = x + 3*SCALE; pp[3] = y + 3*SCALE; vsl_type(display, SOLID); vsf_interior(display, SOLID); v_bar(display, pp); } else { switch (type) { case 'P': /* Planet */ /* * Draw a cross at the location; first the * horizontal, then the vertical line. */ pp[0] = x - radius; pp[2] = x + radius; pp[1] = pp[3] = y; v_pline(display, 2, pp); pp[0] = pp[2] = x; pp[1] = y - radius; pp[3] = y + radius; v_pline(display, 2, pp); break; case 'D': /* Double */ /* * Split the disk with a horizontal line. */ pp[0] = x - 2*radius; pp[2] = x + 2*radius; pp[1] = pp[3] = y; v_pline(display, 2, pp); goto disk; case 'V': /* Variable */ /* * Draw a circle around the disk. */ vsl_type(display, SOLID); vsf_interior(display, HOLLOW); v_circle(display, x, y, 2*radius); /* Fall through */ default: disk: /* Basic star shape */ vsl_type(display, SOLID); vsf_interior(display, SOLID); v_circle(display, x, y, radius); break; } } } vecsymsgk(x, y, str) char *str; { vecsyms(x, y, str); } draw_text(x, y, str, size, rot) short x, y; char *str; short size; short rot; { short d1, d2, d3; vst_rotation(display, rot*10); vst_height(display, size, &d1, &d2, &d3); v_gtext(display, x, y, str); } #include <signal.h> onward(sig) { signal(sig, onward); } vecclose() { signal(SIGINT, onward); /* Set up for the kill */ signal(SIGTERM, onward); pause(); /* Wait for it */ v_clrwk(display); v_clswk(display); } draw_line(xy_a, xy_b) short xy_a[2], xy_b[2]; { short xy[4]; xy[0] = xy_a[0]; xy[1] = xy_a[1]; xy[2] = xy_b[0]; xy[3] = xy_b[1]; vsl_type(display, linetype); v_pline(display, 2, xy); } prtr_open() { if (v_opnwk(prtr_in, &printer, prtr_out) != 0) return(0); else return(1); } prtr_close() { v_clswk(printer); } SHAR_EOF # End of shell archive exit 0