home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Astrolog (Version 4.00) File: xcharts.c
- **
- ** IMPORTANT NOTICE: the graphics database and chart display routines
- ** used in this program are Copyright (C) 1991-1993 by Walter D. Pullen
- ** (cruiser1@stein.u.washington.edu). Permission is granted to freely
- ** use and distribute these routines provided one doesn't sell,
- ** restrict, or profit from them in any way. Modification is allowed
- ** provided these notices remain with any altered or edited versions of
- ** the program.
- **
- ** The main planetary calculation routines used in this program have
- ** been Copyrighted and the core of this program is basically a
- ** conversion to C of the routines created by James Neely as listed in
- ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
- ** available from Matrix Software. The copyright gives us permission to
- ** use the routines for personal use but not to sell them or profit from
- ** them in any way.
- **
- ** The PostScript code within the core graphics routines are programmed
- ** and Copyright (C) 1992-1993 by Brian D. Willoughby
- ** (brianw@sounds.wa.com). Conditions are identical to those above.
- **
- ** The extended accurate ephemeris databases and formulas are from the
- ** calculation routines in the program "Placalc" and are programmed and
- ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
- ** (alois@azur.ch). The use of that source code is subject to
- ** regulations made by Astrodienst Zurich, and the code is not in the
- ** public domain. This copyright notice must not be changed or removed
- ** by any user of this program.
- **
- ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
- ** X Window graphics initially programmed 10/23-29/1991.
- ** PostScript graphics initially programmed 11/29-30/1992.
- ** Last code change made 12/31/1993.
- */
-
- #include "astrolog.h"
-
- #ifdef GRAPH
-
- /*
- ******************************************************************************
- ** Single Chart Graphics Subprograms.
- ******************************************************************************
- */
-
- /* Given a string, draw it on the screen using the given color. The */
- /* position of the text is based the saved positions of where we drew the */
- /* text the last time the routine was called, being either directly below */
- /* in the same column or in the same row just to the right. This is used */
- /* by the sidebar drawing routine to print a list of text on the chart. */
-
- int DrawPrint(string, m, n)
- char *string;
- int m, n;
- {
- static int x0, x, y;
-
- if (string == NULL) { /* Null string means just initialize position. */
- x0 = x = m; y = n;
- return y;
- }
- if (y >= charty) /* Don't draw if we've scrolled off the chart bottom. */
- return y;
- DrawColor(m);
- DrawText(string, x, y, -1);
-
- /* If the second parameter is TRUE, we stay on the same line, otherwise */
- /* when FALSE we go to the next line at the original column setting. */
-
- if (n)
- x += StringLen(string)*FONTX*scalet;
- else {
- x = x0;
- n = y;
- y += FONTY*scalet;
- }
- return y;
- }
-
-
- /* Print text showing the chart information and house and planet positions */
- /* of a chart in a "sidebar" to the right of the chart in question. This */
- /* is always done for the -v and -w graphic wheel charts unless the -v0 */
- /* switch flag is also set, in which case none of the stuff here is done. */
-
- void DrawInfo()
- {
- char string[STRING];
- int elemode[4][3], elem[4], mo[3], tot, pos, abo, lef, lea, i, y, a, s;
-
- #ifdef INTERPRET
- /* Hack: Just for fun, if interpretation is active (which normally has */
- /* no effect whatsoever on graphics) we'll decorate the chart a little. */
-
- if (interpret) {
- if (screenwidth & 1) {
- /* If screenwidth value is odd, draw a moire pattern in each corner. */
- abo = charty/(screenwidth/10);
- lef = chartx/(screenwidth/10);
- for (y = 0; y <= 1; y++)
- for (i = 0; i <= 1; i++)
- for (s = 0; s <= 1; s++)
- for (a = 1; a < (s ? lef : abo)*2; a++) {
- DrawColor(a & 1 ? gray : off);
- DrawLine(i ? chartx-1-lef : lef, y ? charty-1-abo : abo,
- s ? (i ? chartx-1-a : a) : i*(chartx-1),
- s ? y*(charty-1) : (y ? charty-1-a : a));
- }
- } else {
- /* If screenwidth is even, draw spider web lines in each corner. */
- DrawColor(gray);
- tot = screenwidth*3/20;
- abo = charty/4;
- lef = chartx/4;
- for (y = 0; y <= 1; y++)
- for (i = 0; i <= 1; i++)
- for (a = 1; a < tot; a++)
- DrawLine(i*(chartx-1), y ? (charty-1-a*abo/tot) : a*abo/tot,
- i ? chartx-1-lef+a*lef/tot : lef-a*lef/tot, y*(charty-1));
- }
- }
- #endif
- if (!xtext || (exdisplay & DASHv0) > 0) /* Don't draw sidebar if */
- return; /* -v0 flag is set. */
-
- a = ansi;
- ansi = FALSE;
- seconds = -seconds;
- DrawColor(hilite);
- if (xborder)
- DrawLine(chartx-1, 0, chartx-1, charty-1);
- chartx += SIDET;
- DrawPrint(NULL, chartx-SIDET+FONTX*scalet, FONTY*7/5*scalet);
-
- /* Print chart header and setting information. */
- sprintf(string, "%s %s", appname, VERSION);
- DrawPrint(string, on, FALSE);
- if (Mon == -1)
- sprintf(string, "No time or space.");
- else if (relation == DASHrc)
- sprintf(string, "Composite chart.");
- else {
- sprintf(string, "%c%c%c %s", DAYNAM(DayOfWeek(Mon, Day, Yea)),
- CharDate(Mon, Day, Yea, TRUE));
- DrawPrint(string, hilite, FALSE);
- DrawPrint(CharTime((int)floor(Tim), (int)(FRACT(dabs(Tim))*100.0)),
- hilite, TRUE);
- sprintf(string, " (%d:%02d GMT)", (int)(-Zon),
- (int)(FRACT(dabs(Zon))*100.0+ROUND));
- }
- DrawPrint(string, hilite, FALSE);
- DrawPrint(CharLocation(Lon, Lat, 100.0), hilite, FALSE);
- sprintf(string, "%s houses.", systemname[housesystem]);
- DrawPrint(string, hilite, FALSE);
- sprintf(string, "%s zodiac.", operation & DASHs ? "Siderial" : "Tropical");
- DrawPrint(string, hilite, FALSE);
- sprintf(string, "Julian Day = %10.3f", JulianDayFromTime(T));
- DrawPrint(string, hilite, FALSE);
-
- /* Print house cusp positions. */
- DrawPrint("", hilite, FALSE);
- for (i = 1; i <= SIGNS; i++) {
- sprintf(string, "%2d%s house: ", i, post[i]);
- y = DrawPrint(string, signcolor(i), TRUE);
- if (!seconds && (scale == 100 || !xfont || !xfile) && y < charty) {
- s = scale;
- scale = 100*scalet;
- DrawSign(i, chartx-12*scalet, y-(FONTY/2-1)*scalet);
- scale = s;
- }
- DrawPrint(CharZodiac(house[i]), signcolor(ZTOS(house[i])), FALSE);
- }
-
- /* Print planet positions. */
- DrawPrint("", hilite, FALSE);
- for (i = 1; i <= total; i++) if (!ignore[i]) {
- sprintf(string, seconds ? "%3.3s: " : "%4.4s: ", objectname[i]);
- DrawPrint(string, objectcolor[i], TRUE);
- y = DrawPrint(CharZodiac(planet[i]), signcolor(ZTOS(planet[i])), TRUE);
- if (!seconds && i < S_LO &&
- (scale == 100 || !xfont || !xfile) && y < charty) {
- s = scale;
- scale = 100*scalet;
- DrawObject(i, chartx-12*scalet, y-(FONTY/2-1)*scalet);
- scale = s;
- }
- sprintf(string, "%c ", ret[i] < 0.0 ? 'R' : ' ');
- DrawPrint(string, on, TRUE);
- DrawPrint(CharAltitude(planetalt[i]), hilite, FALSE);
- }
-
- /* Print element table information. */
- DrawPrint("", hilite, FALSE);
- CreateElemTable(elemode, elem, mo, &tot, &pos, &abo, &lef, &lea);
- sprintf(string, "Fire: %d, Earth: %d,", elem[_FIR], elem[_EAR]);
- DrawPrint(string, hilite, FALSE);
- sprintf(string, "Air : %d, Water: %d", elem[_AIR], elem[_WAT]);
- DrawPrint(string, hilite, FALSE);
- sprintf(string, "Car: %d, Fix: %d, Mut: %d", mo[0], mo[1], mo[2]);
- DrawPrint(string, hilite, FALSE);
- sprintf(string, "Yang: %d, Yin: %d", pos, tot-pos);
- DrawPrint(string, hilite, FALSE);
- sprintf(string, "N: %d, S: %d, W: %d, E: %d", abo, tot-abo, tot-lef, lef);
- DrawPrint(string, hilite, FALSE);
- seconds = -seconds;
- ansi = a;
- }
-
-
- /* Draw a wheel chart, in which the 12 signs and houses are delineated, and */
- /* the planets are inserted in their proper places. This is the default */
- /* graphics chart to generate, as is done when the -v or -w (or no) switches */
- /* are included with -X. Draw the aspects in the middle of chart, too. */
-
- void XChartWheel()
- {
- real xsign[SIGNS+1], xhouse[SIGNS+1], xplanet[TOTAL+1], symbol[TOTAL+1];
- int cx, cy, i, j;
- real asc, orb = DEFORB*256.0/(real)charty*(real)SCALE,
- unitx, unity, px, py, temp;
-
- /* Set up variables and temporarily automatically decrease the horizontal */
- /* chart size to leave room for the sidebar if that mode is in effect. */
-
- if (xtext && !(exdisplay & DASHv0))
- chartx -= SIDET;
- cx = chartx/2 - 1; cy = charty/2 - 1;
- unitx = (real)cx; unity = (real)cy;
- asc = xeast ? planet[abs(xeast)]+90*(xeast < 0) : house[1];
- InitCircle();
-
- /* Fill out arrays with the angular degree on the circle of where to */
- /* place each object, cusp, and sign glyph based on how the chart mode. */
-
- if (modex == MODEv) {
- for (i = 1; i <= SIGNS; i++)
- xhouse[i] = PZ(house[i]);
- } else {
- asc -= house[1];
- for (i = 1; i <= SIGNS; i++)
- xhouse[i] = PZ(STOZ(i));
- }
- for (i = 1; i <= SIGNS; i++)
- xsign[i] = PZ(XHousePlaceIn(STOZ(i)));
- for (i = 1; i <= total; i++)
- xplanet[i] = PZ(XHousePlaceIn(planet[i]));
-
- /* Draw Ascendant/Descendant and Midheaven/Nadir lines across whole chart. */
-
- DrawColor(hilite);
- DrawDash(cx+POINT(unitx, 0.99, PX(xhouse[1])),
- cy+POINT(unity, 0.99, PY(xhouse[1])),
- cx+POINT(unitx, 0.99, PX(xhouse[7])),
- cy+POINT(unity, 0.99, PY(xhouse[7])), !xcolor);
- DrawDash(cx+POINT(unitx, 0.99, PX(xhouse[10])),
- cy+POINT(unity, 0.99, PY(xhouse[10])),
- cx+POINT(unitx, 0.99, PX(xhouse[4])),
- cy+POINT(unity, 0.99, PY(xhouse[4])), !xcolor);
-
- /* Draw small five or one degree increments around the zodiac sign ring. */
-
- for (i = 0; i < DEGR; i += 5-(xcolor || psfile || metafile)*4) {
- temp = PZ(XHousePlaceIn((real)i));
- px = PX(temp); py = PY(temp);
- DrawColor(i%5 ? gray : on);
- DrawDash(cx+POINT(unitx, 0.75, px), cy+POINT(unity, 0.75, py),
- cx+POINT(unitx, 0.80, px), cy+POINT(unity, 0.80, py),
- ((psfile || metafile) && i%5)*2);
- }
-
- /* Draw circles for the zodiac sign and house rings. */
-
- DrawColor(on);
- DrawCircle(cx, cy, (int)(unitx*0.95+ROUND), (int)(unity*0.95+ROUND));
- DrawCircle(cx, cy, (int)(unitx*0.80+ROUND), (int)(unity*0.80+ROUND));
- DrawCircle(cx, cy, (int)(unitx*0.75+ROUND), (int)(unity*0.75+ROUND));
- DrawCircle(cx, cy, (int)(unitx*0.65+ROUND), (int)(unity*0.65+ROUND));
-
- /* Draw the glyphs for the signs and houses themselves. */
-
- for (i = 1; i <= SIGNS; i++) {
- temp = xsign[i];
- DrawColor(on);
- DrawLine(cx+POINT(unitx, 0.95, PX(temp)), /* Draw lines separating */
- cy+POINT(unity, 0.95, PY(temp)), /* each sign and house */
- cx+POINT(unitx, 0.80, PX(temp)), /* from each other. */
- cy+POINT(unity, 0.80, PY(temp)));
- DrawLine(cx+POINT(unitx, 0.75, PX(xhouse[i])),
- cy+POINT(unity, 0.75, PY(xhouse[i])),
- cx+POINT(unitx, 0.65, PX(xhouse[i])),
- cy+POINT(unity, 0.65, PY(xhouse[i])));
- if (xcolor && i%3 != 1) { /* Lines from */
- DrawColor(gray); /* each house */
- DrawDash(cx, cy, cx+POINT(unitx, 0.65, PX(xhouse[i])), /* to center */
- cy+POINT(unity, 0.65, PY(xhouse[i])), 1); /* of wheel. */
- }
- temp = Midpoint(temp, xsign[Mod12(i+1)]);
- DrawColor(signcolor(i));
- DrawSign(i, cx+POINT(unitx, 0.875, PX(temp)),
- cy+POINT(unity, 0.875, PY(temp)));
- temp = Midpoint(xhouse[i], xhouse[Mod12(i+1)]);
- DrawHouse(i, cx+POINT(unitx, 0.70, PX(temp)),
- cy+POINT(unity, 0.70, PY(temp)));
- }
- for (i = 1; i <= total; i++) /* Figure out where to put planet glyphs. */
- symbol[i] = xplanet[i];
- FillSymbolRing(symbol);
-
- /* For each planet, draw a small dot indicating where it is, and then */
- /* a line from that point to the planet's glyph. */
-
- for (i = 1; i <= total; i++) if (Proper(i)) {
- if (xlabel) {
- temp = symbol[i];
- DrawColor(ret[i] < 0.0 ? gray : on);
- DrawDash(cx+POINT(unitx, 0.52, PX(xplanet[i])),
- cy+POINT(unity, 0.52, PY(xplanet[i])),
- cx+POINT(unitx, 0.56, PX(temp)),
- cy+POINT(unity, 0.56, PY(temp)),
- (ret[i] < 0.0 ? 1 : 0) - xcolor);
- DrawObject(i, cx+POINT(unitx, 0.60, PX(temp)),
- cy+POINT(unity, 0.60, PY(temp)));
- } else
- DrawColor(objectcolor[i]);
- DrawPoint(cx+POINT(unitx, 0.50, PX(xplanet[i])),
- cy+POINT(unity, 0.50, PY(xplanet[i])));
- }
-
- /* Draw lines connecting planets which have aspects between them. */
-
- if (!xbonus) { /* Don't draw aspects in bonus mode. */
- CreateGrid(FALSE);
- for (j = total; j >= 2; j--)
- for (i = j-1; i >= 1; i--)
- if (grid->n[i][j] && Proper(i) && Proper(j)) {
- DrawColor(aspectcolor[grid->n[i][j]]);
- DrawDash(cx+POINT(unitx, 0.48, PX(xplanet[i])),
- cy+POINT(unity, 0.48, PY(xplanet[i])),
- cx+POINT(unitx, 0.48, PX(xplanet[j])),
- cy+POINT(unity, 0.48, PY(xplanet[j])),
- abs(grid->v[i][j]/60/2));
- }
- }
-
- /* Go draw sidebar with chart information and positions if need be. */
-
- DrawInfo();
- }
-
-
- /* Draw an astro-graph chart on a map of the world, i.e. the draw the */
- /* Ascendant, Descendant, Midheaven, and Nadir lines corresponding to the */
- /* time in the chart. This chart is done when the -L switch is combined */
- /* with the -X switch. */
-
- void XChartAstroGraph()
- {
- real planet1[TOTAL+1], planet2[TOTAL+1],
- end1[TOTAL*2+1], end2[TOTAL*2+1],
- symbol1[TOTAL*2+1], symbol2[TOTAL*2+1],
- lon = Lon, longm, x, y, z, ad, oa, am, od, dm, lat;
- int unit = SCALE, stroke, lat1 = -60, lat2 = 75, y1, y2, xold1, xold2,
- i, j, k, l;
-
- /* Erase top and bottom parts of map. We don't draw the astro-graph lines */
- /* above certain latitudes, and this gives us room for glyph labels, too. */
-
- y1 = (91-lat1)*SCALE;
- y2 = (91-lat2)*SCALE;
- DrawColor(off);
- DrawBlock(1, 1, chartx-2, y2-1);
- DrawBlock(1, charty-2, chartx-2, y1+1);
- DrawColor(hilite);
- DrawDash(0, charty/2, chartx-2, charty/2, 4); /* Draw equator. */
- DrawColor(on);
- DrawLine(1, y2, chartx-2, y2);
- DrawLine(1, y1, chartx-2, y1);
- for (i = 1; i <= total*2; i++)
- end1[i] = end2[i] = -LARGE;
-
- /* Draw small hatches every 5 degrees along edges of world map. */
-
- DrawColor(hilite);
- for (i = lat1; i <= lat2; i += 5) {
- j = (91-i)*SCALE;
- k = (2+(i%10 == 0)+2*(i%30 == 0))*scalet;
- DrawLine(1, j, k, j);
- DrawLine(chartx-2, j, chartx-1-k, j);
- }
- for (i = -180; i < 180; i += 5) {
- j = (180-i)*SCALE;
- k = (2+(i%10 == 0)+2*(i%30 == 0)+(i%90 == 0))*scalet;
- DrawLine(j, y2+1, j, y2+k);
- DrawLine(j, y1-1, j, y1-k);
- }
-
- #ifdef MATRIX
- /* Calculate zenith locations of each planet. */
-
- for (i = 1; i <= total; i++) {
- planet1[i] = DTOR(planet[i]);
- planet2[i] = DTOR(planetalt[i]);
- EclToEqu(&planet1[i], &planet2[i]);
- }
-
- /* Draw the Midheaven lines and zenith location markings. */
-
- if (lon < 0.0)
- lon += DEGREES;
- for (i = 1; i <= total; i++) if (Proper(i)) {
- x = DTOR(MC)-planet1[i];
- if (x < 0.0)
- x += 2.0*PI;
- if (x > PI)
- x -= 2.0*PI;
- z = lon+RTOD(x);
- if (z > DEGHALF)
- z -= DEGREES;
- j = (int) (Mod(DEGHALF-z+degree)*(real)SCALE);
- DrawColor(elemcolor[_EAR]);
- DrawLine(j, y1+unit*4, j, y2-unit*1);
- end2[i*2-1] = (real) j;
- y = RTOD(planet2[i]);
- k = (int) ((91.0-y)*(real)SCALE);
- DrawColor(hilite);
- DrawBlock(j-1, k-1, j+1, k+1);
- DrawColor(off);
- DrawBlock(j, k, j, k);
-
- /* Draw Nadir lines assuming we aren't in bonus chart mode. */
-
- if (!xbonus) {
- j += 180*SCALE;
- if (j > chartx-2)
- j -= (chartx-2);
- end1[i*2-1] = (real) j;
- DrawColor(elemcolor[_WAT]);
- DrawLine(j, y1+unit*2, j, y2-unit*2);
- }
- }
-
- /* Now, normally, unless we are in bonus chart mode, we will go on to draw */
- /* the Ascendant and Descendant lines here. */
-
- longm = DTOR(Mod(MC+lon));
- if (!xbonus) for (i = 1; i <= total; i++) if (Proper(i)) {
- xold1 = xold2 = -1000;
-
- /* Hack: Normally we draw the Ascendant and Descendant line segments */
- /* simultaneously. However, for the PostScript and metafile stroke */
- /* graphics, this will case the file to get inordinately large due to */
- /* the constant thrashing between the Asc and Desc colors. Hence for */
- /* these charts only, we'll do two passes for Asc and Desc. */
- stroke = psfile || metafile;
- for (l = 0; l <= stroke; l++)
-
- for (lat = (real)lat1; lat <= (real)lat2;
- lat += 1.0/(real)(SCALE/scalet)) {
-
- /* First compute and draw the current segment of Ascendant line. */
-
- j = (int) ((91.0-lat)*(real)SCALE);
- ad = tan(planet2[i])*tan(DTOR(lat));
- if (ad*ad > 1.0)
- ad = LARGE;
- else {
- ad = ASIN(ad);
- oa = planet1[i]-ad;
- if (oa < 0.0)
- oa += 2.0*PI;
- am = oa-PI/2.0;
- if (am < 0.0)
- am += 2.0*PI;
- z = longm-am;
- if (z < 0.0)
- z += 2.0*PI;
- if (z > PI)
- z -= 2.0*PI;
- z = RTOD(z);
- k = (int) (Mod(DEGHALF-z+degree)*(real)SCALE);
- if (!stroke || !l) {
- DrawColor(elemcolor[_FIR]);
- DrawWrap(xold1, j+scalet, k, j, 1, chartx-2);
- if (lat == (real) lat1) { /* Line segment */
- DrawLine(k, y1, k, y1+unit*4); /* pointing to */
- end2[i*2] = (real) k; /* Ascendant. */
- }
- } else if (lat == (real) lat1)
- end2[i*2] = (real) k;
- xold1 = k;
- }
-
- /* The curving Ascendant and Descendant lines actually touch each at */
- /* low latitudes. Sometimes when we start out, a particular planet's */
- /* lines haven't appeared yet, i.e. we are scanning at a latitude */
- /* where our planet's lines don't exist. If this is the case, then */
- /* when they finally do start, draw a thin horizontal line connecting */
- /* the Ascendant and Descendant lines so they don't just start in */
- /* space. Note that these connected lines aren't labeled with glyphs. */
-
- if (ad == LARGE) {
- if (xold1 >= 0) {
- if (!stroke || !l) {
- DrawColor(gray);
- DrawWrap(xold1, j+1, xold2, j+1, 1, chartx-2);
- }
- lat = DEGQUAD;
- }
- } else {
-
- /* Then compute and draw corresponding segment of Descendant line. */
-
- od = planet1[i]+ad;
- dm = od+PI/2.0;
- z = longm-dm;
- if (z < 0.0)
- z += 2.0*PI;
- if (z > PI)
- z -= 2.0*PI;
- z = RTOD(z);
- k = (int) (Mod(DEGHALF-z+degree)*(real)SCALE);
- if (xold2 < 0 && lat > (real)lat1 && (!stroke || l)) {
- DrawColor(gray);
- DrawWrap(xold1, j, k, j, 1, chartx-2);
- }
- if (!stroke || l) {
- DrawColor(elemcolor[_AIR]);
- DrawWrap(xold2, j+scalet, k, j, 1, chartx-2);
- if (lat == (real)lat1) /* Line segment */
- DrawLine(k, y1, k, y1+unit*2); /* pointing to */
- } /* Descendant. */
- xold2 = k;
- }
- }
- #endif /* MATRIX */
-
- /* Draw segments pointing to top of Ascendant and Descendant lines. */
-
- if (ad != LARGE) {
- DrawColor(elemcolor[_FIR]);
- DrawLine(xold1, y2, xold1, y2-unit*1);
- DrawColor(elemcolor[_AIR]);
- DrawLine(k, y2, k, y2-unit*2);
- end1[i*2] = (real) k;
- }
- }
- DrawColor(maincolor[5]);
- DrawPoint((int)((181.0-Lon)*(real)SCALE),
- (int)((91.0-Lat)*(real)SCALE));
-
- /* Determine where to draw the planet glyphs. We have four sets of each */
- /* planet - each planet's glyph appearing in the chart up to four times - */
- /* one for each type of line. The Midheaven and Ascendant lines are always */
- /* labeled at the bottom of the chart, while the Nadir and Midheaven lines */
- /* at the top. Therefore we need to place two sets of glyphs, twice. */
-
- for (i = 1; i <= total*2; i++) {
- symbol1[i] = end1[i];
- symbol2[i] = end2[i];
- }
- FillSymbolLine(symbol1);
- FillSymbolLine(symbol2);
-
- /* Now actually draw the planet glyphs. */
-
- for (i = 1; i <= total*2; i++) {
- j = (i+1)/2;
- if (Proper(j)) {
- if ((turtlex = (int) symbol1[i]) > 0 && xlabel) {
- DrawColor(ret[j] < 0.0 ? gray : on);
- DrawDash((int) end1[i], y2-unit*2, (int) symbol1[i], y2-unit*4,
- (ret[i] < 0.0 ? 1 : 0) - xcolor);
- DrawObject(j, turtlex, y2-unit*10);
- }
- if ((turtlex = (int) symbol2[i]) > 0) {
- DrawColor(ret[j] < 0.0 ? gray : on);
- DrawDash((int) end2[i], y1+unit*4, (int) symbol2[i], y1+unit*8,
- (ret[i] < 0.0 ? 1 : 0) - xcolor);
- DrawObject(j, turtlex, y1+unit*14);
- DrawTurtle(objectdraw[i & 1 ? _MC : _ASC], (int) symbol2[i],
- y1+unit*24);
- }
- }
- }
- }
-
-
- /* Draw an aspect and midpoint grid in the window, with planets labeled down */
- /* the diagonal. This chart is done when the -g switch is combined with the */
- /* -X switch. The chart always has a certain number of cells; hence based */
- /* how the restrictions are set up, there may be blank columns and rows, */
- /* or else only the first number of unrestricted objects will be included. */
-
- void XChartGrid()
- {
- char string[STRING];
- int unit, siz, x, y, i, j, k;
- colpal c;
-
- unit = CELLSIZE*SCALE; siz = gridobjects*unit;
- CreateGrid(xbonus);
-
- /* Loop through each cell in each row and column of grid. */
-
- for (y = 1, j = 0; y <= gridobjects; y++) {
- do {
- j++;
- } while (ignore[j] && j <= total);
- DrawColor(gray);
- DrawDash(0, y*unit, siz, y*unit, !xcolor);
- DrawDash(y*unit, 0, y*unit, siz, !xcolor);
- if (j <= total) for (x = 1, i = 0; x <= gridobjects; x++) {
- do {
- i++;
- } while (ignore[i] && i <= total);
- if (i <= total) {
- turtlex = x*unit-unit/2;
- turtley = y*unit-unit/2 - (SCALE/scalet > 2 ? 5*scalet : 0);
-
- /* If this is an aspect cell, draw glyph of aspect in effect. */
-
- if (xbonus ? x > y : x < y) {
- DrawColor(c = aspectcolor[grid->n[i][j]]);
- DrawAspect(grid->n[i][j], turtlex, turtley);
-
- /* If this is a midpoint cell, draw glyph of sign of midpoint. */
-
- } else if (xbonus ? x < y : x > y) {
- DrawColor(c = signcolor(grid->n[i][j]));
- DrawSign(grid->n[i][j], turtlex, turtley);
-
- /* For cells on main diagonal, draw glyph of planet. */
-
- } else {
- DrawColor(hilite);
- DrawEdge((y-1)*unit, (y-1)*unit, y*unit, y*unit);
- DrawObject(i, turtlex, turtley);
- }
-
- /* When the scale size is 300, we can print text in each cell: */
-
- if (SCALE/scalet > 2 && xlabel) {
- k = abs(grid->v[i][j]);
-
- /* For the aspect portion, print the orb in degrees and minutes. */
-
- if (xbonus ? x > y : x < y) {
- if (grid->n[i][j])
- sprintf(string, "%c%d %02d'", k != grid->v[i][j] ? '-' : '+',
- k/60, k%60);
- else
- sprintf(string, "");
-
- /* For the midpoint portion, print the degrees and minutes. */
-
- } else if (xbonus ? x < y : x > y)
- sprintf(string, "%2d %02d'", k/60, k%60);
-
- /* For the main diagonal, print degree and sign of each planet. */
-
- else {
- c = signcolor(grid->n[i][j]);
- sprintf(string, "%c%c%c %02d", SIGNAM(grid->n[i][j]), k);
- }
- DrawColor(c);
- DrawText(string, x*unit-unit/2, y*unit-3*scalet, TRUE);
- }
- }
- }
- }
- }
-
-
- /* Draw the local horizon, and draw in the planets where they are at the */
- /* time in question, as done when the -Z is combined with the -X switch. */
-
- void XChartHorizon()
- {
- real lon, lat,
- lonz[TOTAL+1], latz[TOTAL+1], azi[TOTAL+1], alt[TOTAL+1];
- int x[TOTAL+1], y[TOTAL+1], m[TOTAL+1], n[TOTAL+1],
- cx = chartx / 2, cy = charty / 2, unit = 12*SCALE,
- x1, y1, x2, y2, xs, ys, i, j, k, l;
-
- /* Make a slightly smaller rectangle within the window to draw the planets */
- /* in. Make segments on all four edges marking 5 degree increments. */
-
- x1 = y1 = unit/2; x2 = chartx-x1; y2 = charty-y1;
- xs = x2-x1; ys = y2-y1;
- DrawColor(hilite);
- for (i = 0; i < 180; i += 5) {
- j = y1+(int)((real)i*(real)ys/DEGHALF);
- k = (2+(i%10 == 0)+2*(i%30 == 0))*scalet;
- DrawLine(x1+1, j, x1+1+k, j);
- DrawLine(x2-1, j, x2-1-k, j);
- }
- for (i = 0; i < DEGR; i += 5) {
- j = x1+(int)((real)i*(real)xs/DEGREES);
- k = (2+(i%10 == 0)+2*(i%30 == 0))*scalet;
- DrawLine(j, y1+1, j, y1+1+k);
- DrawLine(j, y2-1, j, y2-1-k);
- }
-
- /* Draw vertical lines dividing our rectangle into four areas. In our */
- /* local space chart, the middle line represents due south, the left line */
- /* due east, the right line due west, and the edges due north. A fourth */
- /* horizontal line divides that which is above and below the horizon. */
-
- DrawColor(gray);
- DrawDash(cx, y1, cx, y2, 1);
- DrawDash((cx+x1)/2, y1, (cx+x1)/2, y2, 1);
- DrawDash((cx+x2)/2, y1, (cx+x2)/2, y2, 1);
- DrawColor(on);
- DrawEdge(x1, y1, x2, y2);
- DrawDash(x1, cy, x2, cy, 1);
-
- /* Calculate the local horizon coordinates of each planet. First convert */
- /* zodiac position and declination to zenith longitude and latitude. */
-
- lon = DTOR(Mod(Lon)); lat = DTOR(Lat);
- for (i = 1; i <= total; i++) {
- lonz[i] = DTOR(planet[i]); latz[i] = DTOR(planetalt[i]);
- EclToEqu(&lonz[i], &latz[i]);
- }
- for (i = 1; i <= total; i++) if (Proper(i)) {
- lonz[i] = DTOR(Mod(RTOD(lonz[_MC]-lonz[i]+PI/2.0)));
- EquToLocal(&lonz[i], &latz[i], PI/2.0-lat);
- azi[i] = DEGREES-RTOD(lonz[i]); alt[i] = RTOD(latz[i]);
- x[i] = x1+(int)((real)xs*(Mod(DEGQUAD-azi[i]))/DEGREES+ROUND);
- y[i] = y1+(int)((real)ys*(DEGQUAD-alt[i])/DEGHALF+ROUND);
- m[i] = x[i]; n[i] = y[i]+unit/2;
- }
-
- /* As in the DrawGlobe() routine, we now determine where to draw the */
- /* glyphs in relation to the actual points, so that the glyphs aren't */
- /* drawn on top of each other if possible. Again, we assume that we'll */
- /* put the glyph right under the point, unless there would be some */
- /* overlap and the above position is better off. */
-
- for (i = 1; i <= total; i++) if (Proper(i)) {
- k = l = chartx+charty;
- for (j = 1; j < i; j++) if (Proper(j)) {
- k = MIN(k, abs(m[i]-m[j])+abs(n[i]-n[j]));
- l = MIN(l, abs(m[i]-m[j])+abs(n[i]-unit-n[j]));
- }
- if (k < unit || l < unit)
- if (k < l)
- n[i] -= unit;
- }
- for (i = total; i >= 1; i--) if (Proper(i)) /* Draw planet's glyph. */
- DrawObject(i, m[i], n[i]);
- for (i = total; i >= 1; i--) if (Proper(i)) {
- DrawColor(objectcolor[i]);
- if (!xbonus || i > BASE)
- DrawPoint(x[i], y[i]); /* Draw small or large dot */
- else /* near glyph indicating */
- DrawSpot(x[i], y[i]); /* exact local location. */
- }
- }
-
-
- /* Draw the local horizon, and draw in the planets where they are at the */
- /* time in question. This chart is done when the -Z0 is combined with the */
- /* -X switch. This is an identical function to XChartHorizon(); however, */
- /* that routine's chart is entered on the horizon and meridian. Here we */
- /* center the chart around the center of the sky straight up from the */
- /* local horizon, with the horizon itself being an encompassing circle. */
-
- void XChartHorizonSky()
- {
- real lon, lat, rx, ry, s, a, sqr2,
- lonz[TOTAL+1], latz[TOTAL+1], azi[TOTAL+1], alt[TOTAL+1];
- int x[TOTAL+1], y[TOTAL+1], m[TOTAL+1], n[TOTAL+1],
- cx = chartx / 2, cy = charty / 2, unit = 12*SCALE, i, j, k, l;
-
- /* Draw a circle in window to indicate horizon line, lines dividing */
- /* the window into quadrants to indicate n/s and w/e meridians, and */
- /* segments on these lines and the edges marking 5 degree increments. */
-
- sqr2 = sqrt(2.0);
- DrawColor(gray);
- DrawDash(cx, 0, cx, charty-1, 1);
- DrawDash(0, cy, chartx-1, cy, 1);
- DrawColor(hilite);
- for (i = -125; i <= 125; i += 5) {
- k = (2+(i/10*10 == i ? 1 : 0)+(i/30*30 == i ? 2 : 0))*scalet;
- s = 1.0/(DEGQUAD*sqr2);
- j = cy+(int)(s*cy*i);
- DrawLine(cx-k, j, cx+k, j);
- j = cx+(int)(s*cx*i);
- DrawLine(j, cy-k, j, cy+k);
- }
- for (i = 5; i < 55; i += 5) {
- k = (2+(i/10*10 == i ? 1 : 0)+(i/30*30 == i ? 2 : 0))*scalet;
- s = 1.0/(DEGHALF-DEGQUAD*sqr2);
- j = (int)(s*cy*i);
- DrawLine(0, j, k, j);
- DrawLine(0, charty-1-j, k, charty-1-j);
- DrawLine(chartx-1, j, chartx-1-k, j);
- DrawLine(chartx-1, charty-1-j, chartx-1-k, charty-1-j);
- j = (int)(s*cx*i);
- DrawLine(j, 0, j, k);
- DrawLine(chartx-1-j, 0, chartx-1-j, k);
- DrawLine(j, charty-1, j, charty-1-k);
- DrawLine(chartx-1-j, charty-1, chartx-1-j, charty-1-k);
- }
- rx = cx/sqr2; ry = cy/sqr2;
- DrawColor(on);
- DrawCircle(cx, cy, (int)rx, (int)ry);
- InitCircle();
- for (i = 0; i < DEGR; i += 5) {
- k = (2+(i/10*10 == i ? 1 : 0)+(i/30*30 == i ? 2 : 0))*scalet;
- DrawLine(cx+(int)((rx-k)*circ->x[i]), cy+(int)((ry-k)*circ->y[i]),
- cx+(int)((rx+k)*circ->x[i]), cy+(int)((ry+k)*circ->y[i]));
- }
-
- /* Calculate the local horizon coordinates of each planet. First convert */
- /* zodiac position and declination to zenith longitude and latitude. */
-
- lon = DTOR(Mod(Lon)); lat = DTOR(Lat);
- for (i = 1; i <= total; i++) {
- lonz[i] = DTOR(planet[i]); latz[i] = DTOR(planetalt[i]);
- EclToEqu(&lonz[i], &latz[i]);
- }
- for (i = 1; i <= total; i++) if (Proper(i)) {
- lonz[i] = DTOR(Mod(RTOD(lonz[_MC]-lonz[i]+PI/2.0)));
- EquToLocal(&lonz[i], &latz[i], PI/2.0-lat);
- azi[i] = a = DEGREES-RTOD(lonz[i]); alt[i] = DEGQUAD-RTOD(latz[i]);
- s = alt[i]/DEGQUAD;
- x[i] = cx+(int)(rx*s*COSD(DEGHALF+azi[i])+ROUND);
- y[i] = cy+(int)(ry*s*SIND(DEGHALF+azi[i])+ROUND);
- if (!ISCHART(x[i], y[i]))
- x[i] = -1000;
- m[i] = x[i]; n[i] = y[i]+unit/2;
- }
-
- /* As in the DrawGlobe() routine, we now determine where to draw the */
- /* glyphs in relation to the actual points, so that the glyphs aren't */
- /* drawn on top of each other if possible. Again, we assume that we'll */
- /* put the glyph right under the point, unless there would be some */
- /* overlap and the above position is better off. */
-
- for (i = 1; i <= total; i++) if (Proper(i)) {
- k = l = chartx+charty;
- for (j = 1; j < i; j++) if (Proper(j)) {
- k = MIN(k, abs(m[i]-m[j])+abs(n[i]-n[j]));
- l = MIN(l, abs(m[i]-m[j])+abs(n[i]-unit-n[j]));
- }
- if (k < unit || l < unit)
- if (k < l)
- n[i] -= unit;
- }
- for (i = total; i >= 1; i--) if (m[i] >= 0 && Proper(i)) /* Draw glyph. */
- DrawObject(i, m[i], n[i]);
- for (i = total; i >= 1; i--) if (x[i] >= 0 && Proper(i)) {
- DrawColor(objectcolor[i]);
- if (!xbonus || i > BASE)
- DrawPoint(x[i], y[i]); /* Draw small or large dot */
- else /* near glyph indicating */
- DrawSpot(x[i], y[i]); /* exact local location. */
- }
- }
-
-
- /* Draw a chart depicting an aerial view of the solar system in space, with */
- /* all the planets drawn around the Sun, and the specified central planet */
- /* in the middle, as done when the -S is combined with the -X switch. */
-
- void XChartSpace()
- {
- int x[TOTAL+1], y[TOTAL+1], m[TOTAL+1], n[TOTAL+1],
- cx = chartx / 2, cy = charty / 2, unit, x1, y1, x2, y2, i, j, k, l;
- real sx, sy, sz = 30.0, xp, yp, a;
-
- unit = MAX(xtext*12, 6*SCALE);
- x1 = unit; y1 = unit; x2 = chartx-1-unit; y2 = charty-1-unit;
- unit = 12*SCALE;
-
- /* Determine the scale of the window. For a scale size of 300, make */
- /* the window 6 AU in radius (enough for inner planets out to asteroid */
- /* belt). For a scale of 200, make window 30 AU in radius (enough for */
- /* planets out to Neptune). For scale of 100, make it 90 AU in radius */
- /* (enough for all planets including the orbits of the uranians.) */
-
- if (SCALE < 2)
- sz = 90.0;
- else if (SCALE > 2)
- sz = 6.0;
- sx = (real)(cx-x1)/sz; sy = (real)(cy-y1)/sz;
- for (i = 0; i <= BASE; i++) if (Proper(i)) {
-
- /* Determine what glyph corresponds to our current planet. Normally the */
- /* array indices are the same, however we have to do some swapping for */
- /* non-geocentric based charts where a planet gets replaced with Earth. */
-
- if (centerplanet == 0)
- j = i < 2 ? 1-i : i;
- else if (centerplanet == 1)
- j = i;
- else
- j = i == 0 ? centerplanet : (i == centerplanet ? 0 : i);
- xp = spacex[j]; yp = spacey[j];
- x[i] = cx-(int)(xp*sx); y[i] = cy+(int)(yp*sy);
- m[i] = x[i]; n[i] = y[i]+unit/2;
- }
-
- /* As in the DrawGlobe() routine, we now determine where to draw the */
- /* glyphs in relation to the actual points, so that the glyphs aren't */
- /* drawn on top of each other if possible. Again, we assume that we'll */
- /* put the glyph right under the point, unless there would be some */
- /* overlap and the above position is better off. */
-
- for (i = 0; i <= BASE; i++) if (Proper(i)) {
- k = l = chartx+charty;
- for (j = 0; j < i; j++) if (Proper(j)) {
- k = MIN(k, abs(m[i]-m[j])+abs(n[i]-n[j]));
- l = MIN(l, abs(m[i]-m[j])+abs(n[i]-unit-n[j]));
- }
- if (k < unit || l < unit)
- if (k < l)
- n[i] -= unit;
- }
-
- /* Draw the 12 sign boundaries from the center body to edges of screen. */
-
- a = Mod(RTOD(Angle(spacex[_JUP], spacey[_JUP]))-planet[_JUP]);
- DrawColor(gray);
- for (i = 0; i < SIGNS; i++) {
- k = cx+2*(int)((real)cx*COSD((real)i*30.0+a));
- l = cy+2*(int)((real)cy*SIND((real)i*30.0+a));
- DrawClip(cx, cy, k, l, x1, y1, x2, y2, 1);
- }
- DrawColor(hilite);
- DrawEdge(x1, y1, x2, y2);
- for (i = BASE; i >= 0; i--)
- if (Proper(i) && ISLEGAL(m[i], n[i], x1, y1, x2, y2))
- DrawObject(i, m[i], n[i]);
- for (i = BASE; i >= 0; i--)
- if (Proper(i) && ISLEGAL(x[i], y[i], x1, y1, x2, y2)) {
- DrawColor(objectcolor[i]);
- if (!xbonus || i > BASE)
- DrawPoint(x[i], y[i]); /* Draw small or large dot */
- else /* near glyph indicating */
- DrawSpot(x[i], y[i]); /* exact local location. */
- }
- }
-
-
- /* Draw a chart showing a graphical ephemeris for the given month (or year */
- /* if -Ey in effect), with the date on the vertical access and the zodiac */
- /* on the horizontal, as done when the -E is combined with the -X switch. */
-
- void XChartEphemeris()
- {
- real symbol[TOTAL*2+1];
- char string[4];
- int yea, unit = 6*SCALE, daytot, d = 1, day, mon, monsiz,
- x1, y1, x2, y2, xs, ys, m, n, u, v, i, j;
-
- yea = (exdisplay & DASHEy) > 0; /* Is this -Ey -X or just -E -X? */
- if (yea) {
- daytot = DayInYear(Yea);
- day = 1; mon = 1; monsiz = 31;
- } else
- daytot = DayInMonth(Mon, Yea);
- x1 = yea ? 30 : 24; y1 = unit*2; x2 = chartx - x1; y2 = charty - y1;
- xs = x2 - x1; ys = y2 - y1;
-
- /* Display glyphs of the zodiac along the bottom axis. */
- for (i = 1; i <= SIGNS+1; i++) {
- m = x1 + xs * (i-1) / 12;
- j = i > SIGNS ? 1 : i;
- DrawColor(signcolor(j));
- DrawSign(j, m, y2 + unit);
- DrawColor(gray);
- DrawDash(m, y1, m, y2, 2);
- }
-
- /* Loop and display planet movements for one day segment. */
- while (d <= daytot + 1) {
- n = v;
- v = y1 + MULTDIV(ys, d-1, daytot);
- if (!yea || day == 1) {
- DrawColor(gray);
- DrawDash(x1, v, x2, v, 1); /* Marker line for day or month. */
- }
- if (d > 1)
- for (i = 1; i <= total; i++)
- planet1[i] = planet[i];
- if (yea) {
- MM = mon; DD = day;
- } else {
- MM = Mon; DD = d;
- }
- YY = Yea; TT = 0.0; ZZ = defzone; OO = deflong; AA = deflat;
- CastChart(TRUE);
-
- /* Draw planet glyphs along top of chart. */
- if (d < 2) {
- for (i = 1; i <= total; i++) {
- symbol[i*2-1] = -LARGE;
- if (!Proper(i) || (i == _MOO && xbonus))
- symbol[i*2] = -LARGE;
- else
- symbol[i*2] = planet[i];
- }
- FillSymbolLine(symbol);
- for (i = total; i >= 1; i--)
- if (symbol[i*2] >= 0.0)
- DrawObject(i, x1 + (int)((real)xs * symbol[i*2] / DEGREES), unit);
-
- /* Draw a line segment for each object during this time section. */
- } else
- for (i = total; i >= 1; i--) {
- if (!Proper(i) || (i == _MOO && xbonus))
- continue;
- m = x1 + (int)((real)xs * planet1[i] / DEGREES);
- u = x1 + (int)((real)xs * planet[i] / DEGREES);
- DrawColor(objectcolor[i]);
- DrawWrap(m, n, u, v, x1, x2, objectcolor[i]);
- }
-
- /* Label months or days in the month along the left and right edges. */
- if (d <= daytot && (!yea || day == 1)) {
- if (yea) {
- sprintf(string, "%c%c%c", MONNAM(mon));
- i = (mon == Mon);
- } else {
- sprintf(string, "%2d", d);
- i = (d == Day);
- }
- DrawColor(i ? on : hilite);
- DrawText(string, FONTX *scalet, v + (FONTY-2)*scalet, -1);
- DrawText(string, x2+(FONTX-1)*scalet, v + (FONTY-2)*scalet, -1);
- }
-
- /* Now increment the day counter. For a month we always go up by one. */
- /* For a year we go up by four or until the end of the month reached. */
- if (yea) {
- day += 4;
- if (day > monsiz) {
- d += 4-(day-monsiz-1);
- if (d <= daytot + 1) {
- mon++;
- monsiz = DayInMonth(mon, Yea);
- day = 1;
- }
- } else
- d += 4;
- } else
- d++;
- }
- DrawColor(hilite);
- DrawEdge(x1, y1, x2, y2);
-
- MM = Mon; DD = Day; TT = Tim; /* Recast original chart. */
- CastChart(TRUE);
- }
- #endif /* GRAPH */
-
- /* xcharts.c */
-