Subject: v12i071: StarChart program and Yale star data, Part01/07 Newsgroups: comp.sources.unix Sender: sources Approved: rs@uunet.UU.NET Submitted-by: awpaeth@watcgl.waterloo.edu (Alan W. Paeth) Posting-number: Volume 12, Issue 71 Archive-name: starchart/part01 [ Everything a would-be Carl Sagan needs to get started. --r$ ] This release provides astronomical charting software for locating the stars, planets and other cosmic objects, with output to PIC, PostScript, Tektronix, TTY or HP printing devices. This posting upgrades a previous release (1Q 1987) by adding a Messier catalog database (star clusters, nebulae and galaxies), mnemonic constellation finder, star annotations (eg, star designations in Roman or Greek characters, double- star symbols) and greatly improved command line syntax. A new output driver has been added. A program for updating stellar coordinates (for epoch conversion related to the precession of the equinoxes) is also included. A reposting of "yale.star" which locates the brightest stars (about 9000 entries) accompanyies this software posting. StarChart will run on both the new and old reduced Yale datasets. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by watcgl!awpaeth on Mon Oct 5 18:38:48 EDT 1987 # Contents: README Makefile starchart.h starchart.c stardsp.c starhp.c # starimages.c echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' STARCHART (rev 2) ---------------------------------------------------------------------------- Note: This version is upward compatable with the original "starchart" software family, both in user interface and in continued support of the original reduced Yale catalog. Thus, it may supplant old copies of the software without fear that either shell scripts or file formats will become invalid. However, both the new user interface and the extended catalog are superior, as are extensions for additional labelling (Greek characters, double star indicators, Messier objects), plus a mnemonic "finder" facility. ---------------------------------------------------------------------------- INSTALLATION INSTRUCTIONS: [1] Save the new posting of the reduced Yale Star Catalog under the name "yale.star" (or use a copy of the old version). If the save directory is other than the one in which the program lives, then check out the Makefile, which allows path names to be specified for compilation. Sites without much disk space may truncate the file yale.star at any point, as the data is sorted in order of increasing magnitude (dimming). Additonally, the optional files "messier.star" and "con.locs" should be placed in the chosen directory. Entries in these files are unsorted. The optional file "planet.star" is created on an as-needed basis by the softwaare "planet.c", and might want a home in some less permanent (writable) location. [2] Do a "make all" to compile all software. They are described in the man pages "starchart.1" and "planet.1" . All compile using starchart.c as the mainline, with device driver specifics in modules of appropriate name. [3] You may now try "man test" to make an Orion pic file similar to the one posted to the net. Or you may test by outputting to the tty display, using the version "stardsp". This is described in the EXAMPLE section of the man page. VERSION NOTES: Tty display users (*sigh*) may which to alter "stardsp" to output to the display using an appropriate number of of rows and columns on the screen. (Presently 31x79 for a 32x80 display. 23x79 is a bit sparse). Find the ROWS and COLS #defines in stardsp.c and update. Or be really ambitious and recode them as run time variables. Tektronix emulator users may wish to alter scaling parameters based on the actual physical dimensions of the display raster, to get the cleanest possible star glyphs on output. This is described at length in the beginning of the driver "startek.c". Pic file users: the #define PICFRAG can be adjusted downward (presently 8) should your pic input overflow pic's buffers. This happens when a long move,draw,draw,...,draw sequence happens. Smaller PICFRAGs make larger files, by forming fragmented move,draw commands. PostScript users: you may wish to play with the boiler-plate macros which define star shapes (e.g. 's1' does first magnitude stars). This is mentioned at the end of starchart.c Laserjet users: the output of starlaser must be directed to laserjet via raw connection, because it is largely sent in binary 8-bit format. The graphics memory might overflow if you use the standard (oldest) 59k buffer laserjet (*sigh*). Anyway, I haven't ever lost any relevant data on the sheet: the overflow has occurred on the last few blank pixel rows of the graphics area. If you use laserjet plus, you shouldn't have any problems. Other devices: don't expect the authors to write a new driver for you :-) Look through the sources - it's not so difficult after all... The module "starimages.c" provides support for bitmap devices; the PostScript driver is a good example of generating output in some graphics language. More ambitious programmers may wish to extend the usefulness of these programs. Be our guest, but carefully consider the proposed list of suggestions which intentionally accompanies the main source code body "starchart.c". It is hoped that future changes and major revisions and their subsequent integration will be kept relatively simple by coordinating efforts and by not duplicating work. awpaeth@watcgl (original author and revisions editor) inp@amber.berkeley.EDU (revisionist for user interface) pl@sibelius.intrin.FI (support for mini-Yale, Messier and finder catalogs) @//E*O*F README// chmod u=rwx,g=rwx,o=rwx README echo x - Makefile sed 's/^@//' > "Makefile" <<'@//E*O*F 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 = "./yale.star" # similarly assign the Messier file path: #MESS = "/usr/lib/starchart/messier.star" MESS = "./messier.star" # 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 = "./planet.star" # notice that starchart.o and planet are made dependent on Makefile, due # to the STAR, MESS and PLANET definitions here # put the installation directory here BINDIR = "/usr/local/bin" CFLAGS = -O -DSTARFILE='$(STAR)' -DPLANETFILE='$(PLANET)' -DMESSFILE='$(MESS)' LFLAGS = -O # 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 test: stardsp -c ori all: \ planet\ starhp\ stardsp\ startek\ starpic\ starpost\ starlaser\ epoch\ moonphase install: all strip $(BINS) mv $(BINS) $(BINDIR) starchart.o: starchart.c Makefile starchart.h 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 $@ 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 @//E*O*F Makefile// chmod u=rwx,g=rwx,o=rwx Makefile echo x - starchart.h sed 's/^@//' > "starchart.h" <<'@//E*O*F 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; @//E*O*F starchart.h// chmod u=rwx,g=rwx,o=rwx starchart.h echo x - starchart.c sed 's/^@//' > "starchart.c" <<'@//E*O*F 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 ! ! 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 ! ! 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). ! ! Final integration by the original author [c]. ! Questions, suggestions, and fixes should be e-mailed to him. */ #include #include #include #include #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'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; */ 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); } xform(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) ) { xform(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; switch (subcode[0]) /* vector: check subcode */ { 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 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] == '%') { gkflag = 1; /* Greek Bayer char(s) */ 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; xform(chart, chart->south, chart->west, &xloc, &yloc); xform(chart, chart->south, chart->east, &xloc2, &yloc2); vecmovedraw(xloc, yloc, xloc2, yloc2); xform(chart, chart->north, chart->west, &xloc, &yloc); xform(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; xform(chart, start, chart->west, &xloc, &yloc); vecmove(xloc, yloc); for (i=0; i < div; i++) { start += inc; xform(chart, start, chart->west, &xloc, &yloc); vecdraw(xloc, yloc); } start = chart->south; xform(chart, start, chart->east, &xloc, &yloc); vecmove(xloc, yloc); for (i=0; i < div; i++) { start += inc; xform(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, "%2dh", 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; } 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); xform(chart, chart->south, start, &xloc, &yloc); xform(chart, chart->south, start+inc, &xloc2, &yloc); if (xloc - xloc2 > HTICKLIM) for (ras = start; ras <= stop; ras += inc) { xform(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); xform(chart, start, chart->west, &xloc, &yloc); xform(chart, start+inc, chart->west, &xloc, &yloc2); if (yloc2 - yloc > VTICKLIM) { for (dl = start; dl <= stop; dl += inc) { xform(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); } #define LINELEN 80 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); 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) /* FOUND */ { sscanf(cbuf, "%*5s%f%f%f %[^\n]", &ra, &de, &sc, legend); ra = ftod(ra); de = ftod(de); if ((newline=index(legend, '\n')) != 0) *newline = '\0'; title = legend; return; } } die("Constellation '%s' not found", tag); } /* ! 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 */ @//E*O*F starchart.c// chmod u=rwx,g=rx,o=rx starchart.c echo x - stardsp.c sed 's/^@//' > "stardsp.c" <<'@//E*O*F stardsp.c//' /* * TTY Display driver for starchart.c mainline */ #include #include #include "starchart.h" #define MAX(a,b) ((a)>(b)?(a):(b)) #define ROWS 32 #define COLS 79 /* * Chart parameters (limiting magnitude and window x,y,w,h) */ mapblock thumbnail = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 1.0, 420, 35, 480, 195, 0.0 }; mapblock master = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.9, 2.0, 20, 265, 880, 500, 0.0 }; /* * Generic Star Drawing Stuff */ static int oldx, oldy, scrx, scry; static char **linevec; vecopen() { int i; linevec = (char**)(calloc(ROWS, sizeof(char*))); for (i=0; i0; j--) if (linevec[i][j]) break; for (k=0; k<=j; k++) putchar((c=linevec[i][k]) ? c : ' '); putchar('\n'); free(linevec[i]); } fflush(stdout); free(linevec); } vecsize(points) int points; { } vecmove(x, y) { oldx = x; oldy = y; scrx = (x*COLS+512)/1024; scry = (((768-y)*ROWS)+384)/768; } vecdrawdot(x, y) { vecdraw(x, y); /* dotted and solid the same */ } vecdrawhyph(x, y) { vecdraw(x, y); /* dashed (hyphen) and solid the same */ } vecdraw(x, y) { int dx, dy, savex, savey, i, steps; char c; savex = oldx; savey = oldy; dx = x-oldx; dy = y-oldy; c = (abs(dx) > abs(dy)) ? '-' : '|'; steps = MAX(MAX(abs(dx),abs(dy))/12, 1); for(i=0; i<=steps; i++) { vecmove(savex+(i*dx+steps/2)/steps,savey+(i*dy+steps/2)/steps); sym(c); } } vecsyms(x, y, s) char *s; { char c; vecmove(x, y); while(c = *s++) { sym(c); scrx++; } } vecmovedraw(x1, y1, x2, y2) { vecmove(x1, y1); vecdraw(x2, y2); } drawPlan(x, y) { vecsyms(x, y, "+"); } drawStar(x, y, mag, type, color) char type, *color; { switch (mag) { case -1: draw0(x, y); break; case 0: draw0(x, y); break; case 1: draw1(x, y); break; case 2: draw2(x, y); break; case 3: draw3(x, y); break; case 4: draw4(x, y); break; default: draw5(x, y); break; } } draw0(x, y) { vecsyms(x, y, "O"); } draw1(x, y) { vecsyms(x, y, "*"); } draw2(x, y) { vecsyms(x, y, "o"); } draw3(x, y) { vecsyms(x, y, "-"); } draw4(x, y) { vecsyms(x, y, ","); } draw5(x, y) { vecsyms(x, y, "."); } drawGalx(x, y) { vecsyms(x, y, "@"); } drawNebu(x, y) { vecsyms(x, y, "~"); } drawClus(x, y) { vecsyms(x, y, "%"); } char overwrite(under, over) char under, over; { if (over == under) return(over); if (!under) return(over); if (!over) return(under); if (isspace(under)) return(over); if (isspace(over)) return(under); if (over == '%') return(over); if (over == '~') return(over); if (over == '@') return(over); if (under == '%') return(under); if (under == '~') return(under); if (under == '@') return(under); if ( isalnum(under) && isalnum(over)) return(over); if (!isalnum(under) && isalnum(over)) return(over); if ( isalnum(under) && !isalnum(over)) return(under); if ((under == '-') && (over == '|')) return('+'); if ((under == '|') && (over == '-')) return('+'); if ((under == '+') && (over == '-')) return('+'); if ((under == '+') && (over == '|')) return('+'); if ((under == ',') && (over == '.')) return(';'); if ((under == '.') && (over == ',')) return(';'); if ((under == '.') && (over == '.')) return(':'); if ((under == '|') && (over == '.')) return('!'); if ((under == '|') && (over == ',')) return('!'); if ((under == '.') && (over == '|')) return('!'); if ((under == ',') && (over == '|')) return('!'); if ((under == '.') && (over == '.')) return(':'); return(under); } sym(c) char c; { if ( (scrx >= 0) && (scrx < COLS) && (scry >= 0) && (scry < ROWS) ) linevec[scry][scrx] = overwrite(linevec[scry][scrx], c ); } vecsymsgk(str, x, y) char *str; { vecsyms(str, x, y); } @//E*O*F stardsp.c// chmod u=rwx,g=rwx,o=rwx stardsp.c echo x - starhp.c sed 's/^@//' > "starhp.c" <<'@//E*O*F starhp.c//' /* ** Hewlett-Packard 2623 (and equivalent) graphics terminal ** driver for starchart. ** Low-level routines (starting with 'HP') written and copyrighted by ** Jyrki Yli-Nokari (jty@intrin.FI), ** Petri Launiainen (pl@intrin.FI), ** Intrinsic, Ltd., FINLAND. ** ** You may use this code as you wish if credit is given and this message ** is retained. */ /* ** Star scaling is changed to happen only for the placement, ** therefore the stars look always nice */ #include #include "starchart.h" #define SCALEU 1 #define SCALEL 2 /* ** Chart parameters (limiting magnitude and window x,y,w,h) */ mapblock thumbnail = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.2, 1.0, 420, 35, 480, 195, 0.0 }; mapblock master = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.0, 3.0, 20, 265, 880, 500, 0.0 }; /* ** Generic functions */ vecopen () { HPplot (); HPclear (); } vecclose () { fflush (stdout); } vecsize (points) int points; { } vecmove (x, y) int x,y; { x = SCALEU*x/SCALEL; /* adjust to screen size */ y = SCALEU*y/SCALEL; HPmove (x, y); } vecdraw (x, y) int x,y; { x = SCALEU*x/SCALEL; /* adjust to screen size */ y = SCALEU*y/SCALEL; HPdraw (x, y); } vecdrawdot(x, y) { vecdraw(x, y); /* solid and dotted currently the same */ } vecdrawhyph(x, y) { vecdraw(x, y); /* solid and dashed currently the same */ } xvecsym (x, y, s) int x,y; char s; { y -= 11; /* center character strings */ x = SCALEU*x/SCALEL; /* adjust to screen size */ y = SCALEU*y/SCALEL; HPmove (x, y-11); /* center character strings */ HPalpha_on (); putchar (s); HPalpha_off (); } vecsyms (x, y, s) int x,y; char *s; { y -= 11; /* center character strings */ x = SCALEU*x/SCALEL; /* adjust to screen size */ y = SCALEU*y/SCALEL; HPmove (x, y); HPalpha_on (); fputs (s, stdout); HPalpha_off (); } vecmovedraw (x1, y1, x2, y2) int x1, x2, y1, y2; { x1 = SCALEU*x1/SCALEL; /* adjust to screen size */ y1 = SCALEU*y1/SCALEL; x2 = SCALEU*x2/SCALEL; /* adjust to screen size */ y2 = SCALEU*y2/SCALEL; HPmove (x1, y1); HPdraw (x2, y2); } drawlen (x, y, dx, dy, len) int x, y, dx, dy, len; { x = SCALEU*x/SCALEL; /* adjust to screen size */ y = SCALEU*y/SCALEL; HPmove (x + dx, y + dy); HPdraw (x + dx + len - 1, y+dy); } /* ** Low Level HP Plotting Routines */ HPplot () /* switch to plot mode */ { fputs ("\033*dcl0,0P\033&k1O\033*m1g", stdout); /* ** 1. Enable graphics display. ** 2. Disable cursor. ** 3. Locate cursor to origin. ** 4. Enable Graphics pad. ** 5. Solid area fill */ } HPalpha_on () /* switch to alpha mode */ { fputs ("\033*dS", stdout); } HPalpha_off () /* switch back to plot mode */ { fputs ("\033*dT", stdout); } HPclear () { fputs ("\033*dA\033*m2a1B", stdout); /* ** 1. Clear graphics screen. ** 2. Draw in "set pixel" mode. ** 3. Select solid line. */ fflush (stdout); } HPmove (x, y) /* move to (x,y) */ int x, y; { printf ("\033*pa%d,%dZ", x, y); } HPdraw (x, y) /* draw to (x,y) */ int x, y; { printf ("\033*pb%d,%dZ", x, y); } vecsymsgk(str, x, y) char *str; { vecsyms(str, x, y); } @//E*O*F starhp.c// chmod u=rwx,g=rwx,o=rwx starhp.c echo x - starimages.c sed 's/^@//' > "starimages.c" <<'@//E*O*F starimages.c//' /* ** This file defines the star and planet images for vector type devices. ** All vector formed images are here (for tektronix, hp series and laserjet) ** ** Original images by Alan W. Paeth, dynamic 'star compilation' and ** cluster/galaxy images added by (pl) 15-Mar-87 */ #include #define IMAROWS 20 #define IMACOLS 20 /* both should be more than plenty */ #define ENDCOORD 32767 /* should be out of offset range */ /********************************************************************** ** ** cstar: ** ** Parameters: ** ptr char pointer to star row, or NULL to compile ** ** Function: ** 'compiles' star image data for starlen from char pointers given ** this method simplifies the creation and updating of images. ** Image can consist of max IMAROWS of data, and the maximum ** length/row is IMACOLS. The lengths of rows MUST be equal !! ** ** Returns: ** NULL when ptr != NULL, pointer to allocated vector defining ** drawlen information and ending to ENDCOORD value when ptr == NULL ** ** History: ** */ int * cstar (ptr) char *ptr; { static int n; /* number of lines gathered */ static int len; /* longest line found */ static char image [IMAROWS][IMACOLS+1]; /* image data area */ int cx, cy; /* center points */ int *retarea; int i,j, x, y, s, l; /* ** this is a two state machine - first it just gathers ptr strings ** until NULL is given, then it 'compiles' the previous strings ** and returns offset values for printing the star. */ if (ptr != NULL) { /* gather */ strcpy (image [n++], ptr); /* copy data */ cx = strlen (ptr); /* get max len */ if (cx > len) len = cx; return NULL; } /* else { /* start 'compilation' */ cy = n / 2; /* align */ cx = len / 2; /* ** allocate offset area */ retarea = (int *) calloc (len * n * (n / 2 + 1) * 3 + 1, sizeof (int)); if (retarea == NULL) { perror ("Memory allocation failed"); exit (2); } /* ** fill return area */ j = 0; for (i = 0; i < n; i++) { l = 0; s = 0; x = 0; ptr = image [i]; while (*ptr) { if (*ptr == ' ') { if (l) { /* flush */ retarea [j++] = s - cx; retarea [j++] = i - cy; retarea [j++] = l; l = 0; } } else { if (l) l++; else { s = x; l = 1; } } ptr++; x++; } /* while */ if (l) { /* flush */ retarea [j++] = s - cx; retarea [j++] = i - cy; retarea [j++] = l; } } /* for */ n = 0; retarea [j] = ENDCOORD; return retarea; } /* cstar */ drawPlan(x, y) int x,y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" *** "); (void) cstar ("* *"); (void) cstar ("*****"); (void) cstar ("* *"); (void) cstar (" *** "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } drawStar (x, y, mag, type, color) int x, y, mag; char type, *color; { switch (mag) { case -1: case 0: draw0 (x, y); break; case 1: draw1 (x, y); break; case 2: draw2 (x, y); break; case 3: draw3 (x, y); break; case 4: draw4 (x, y); break; default: draw5 (x, y); break; } } draw0(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" ***** "); (void) cstar ("*******"); (void) cstar ("*** ***"); (void) cstar ("** **"); (void) cstar ("*** ***"); (void) cstar ("*******"); (void) cstar (" ***** "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } draw1(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" *** "); (void) cstar ("*****"); (void) cstar ("*****"); (void) cstar ("*****"); (void) cstar (" *** "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } draw2(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" * "); (void) cstar (" *** "); (void) cstar ("*****"); (void) cstar (" *** "); (void) cstar (" * "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } draw3(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar ("***"); (void) cstar ("***"); (void) cstar ("***"); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } draw4(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" * "); (void) cstar ("***"); (void) cstar (" * "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } draw5(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar ("*"); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } drawGalx(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" *** "); (void) cstar ("* "); (void) cstar (" *** "); (void) cstar (" *"); (void) cstar (" *** "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } drawClus(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" * * "); (void) cstar ("* * *"); (void) cstar (" * * "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } drawNebu(x, y) int x, y; { static int def, *coord; int i; if (! def) { def = 1; (void) cstar (" ** "); (void) cstar ("* *"); (void) cstar (" ** "); coord = cstar (NULL); } i = 0; while (coord [i] != ENDCOORD) { drawlen (x, y, coord [i], coord [i+1], coord [i+2]); i += 3; } } @//E*O*F starimages.c// chmod u=rwx,g=rwx,o=rwx starimages.c exit 0