This is charts.c in view mode; [Download] [Up]
/*
** Astrolog (Version 4.10) File: charts.c
**
** IMPORTANT NOTICE: the graphics database and chart display routines
** used in this program are Copyright (C) 1991-1994 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 3/19/1994.
*/
#include "astrolog.h"
/*
******************************************************************************
** Single Chart Display Subprograms.
******************************************************************************
*/
/* Fill out tables based on the number of unrestricted planets in signs by */
/* element, signs by mode, as well as other values such as the number of */
/* objects in yang vs. yin signs, in various house hemispheres (north/south */
/* and east/west), and the number in first six signs vs. second six signs. */
/* This is used by the -v chart listing and the sidebar in graphics charts. */
void CreateElemTable(elemode, elem, mo, tot, pos, abo, lef, lea)
int elemode[4][3], *elem, *mo, *tot, *pos, *abo, *lef, *lea;
{
int i, j;
*tot = *pos = *abo = *lef = *lea = 0; /* Initialize arrays */
for (i = 0; i < 4; i++) /* and variables to zero */
elem[i] = 0;
for (j = 0; j < 3; j++)
mo[j] = 0;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
elemode[i][j] = 0;
/* Calculate number of objects in each element, mode, hemisphere, etc. */
for (i = 1; i <= total; i++) if (!ignore[i]) {
(*tot)++;
j = ZTOS(planet[i]);
elemode[(j-1)&3][(j-1)%3]++;
elem[(j-1)&3]++; mo[(j-1)%3]++;
*pos += (j & 1);
*lea += (j < _LIB);
j = inhouse[i];
*abo += (j >= _LIB);
*lef += (j < _CAN || j >= _CAP);
}
}
/* Print the straight listing of planet and house positions and specified */
/* by the -v switch, along with the element table, etc. */
void ChartLocation()
{
int elemode[4][3], elem[4], mo[3], pos, abo, lef, lea;
int count, i, j, k;
CreateElemTable(elemode, elem, mo, &count, &pos, &abo, &lef, &lea);
/* Print header showing time and date of the chart being displayed. */
AnsiColor(WHITE);
fprintf(S, "%s %s chart ", appname, VERSION);
if (Mon == -1)
fprintf(S, "(no time or space)\n");
else if (relation == DASHrc)
fprintf(S, "(composite)\n");
else {
i = (int) (FRACT(dabs(Tim))*100.0+ROUND/60.0);
fprintf(S, "for %s %s",
CharDate(Mon, Day, Yea, TRUE), CharTime((int)Tim, i));
fprintf(S, " (%s GMT) %s\n", CharZone(Zon),
CharLocation(Lon, Lat, 100.0));
}
#ifdef INTERPRET
if (interpret) { /* Print an interpretation if -I in effect. */
if (relation == DASHr)
InterpretSynastry(); /* Print synastry interpretaion for -r -I. */
else
InterpretLocation(); /* Do normal interpretation for just -v -I. */
return;
}
#endif
AnsiColor(DEFAULT);
fprintf(S, "Body Locat. Ret. Decl. Rul. House Rul. Veloc. ");
fprintf(S, "%s Houses.\n\n", systemname[housesystem]);
/* Ok, now print out each location of each object. */
for (i = 1, j = 1; i <= BASE; i++, j++) {
if (i > OBJECTS && (i <= C_HI || ignore[i]))
continue;
while (i <= OBJECTS && j <= OBJECTS && ignore[j])
j++;
if (i <= OBJECTS && j > OBJECTS)
PrintTab(' ', 51);
else {
if (i > OBJECTS)
j = i;
AnsiColor(objectansi[j]);
fprintf(S, "%-4.4s: ", objectname[j]);
PrintZodiac(planet[j]);
fprintf(S, " %c ", ret[j] >= 0.0 ? ' ' : 'R');
if (j <= THINGS || j > OBJECTS)
PrintAltitude(planetalt[i]);
else
fprintf(S, "_______");
fprintf(S, " (%c)", Dignify(j, ZTOS(planet[i])));
k = inhouse[j];
AnsiColor(signansi(k));
fprintf(S, " [%2d%c%c house]", k, post[k][0], post[k][1]);
AnsiColor(DEFAULT);
fprintf(S, " [%c] ", Dignify(j, k));
if ((j != _MOO || placalc) && (IsObject(j) || (j == _NOD && placalc)))
fprintf(S, RTOD(dabs(ret[j])) < 10.0 ? "%c%5.3f" : "%c%5.2f",
ret[i] < 0.0 ? '-' : '+', RTOD(dabs(ret[j])));
else
fprintf(S, "______");
}
/* For some lines, we have to append the house cusp positions. */
if (i <= SIGNS) {
fprintf(S, " - ");
AnsiColor(signansi(i));
fprintf(S, "House cusp %2d: ", i);
PrintZodiac(house[i]);
}
/* For some lines, we have to append the element table information. */
if (i == SIGNS+2)
fprintf(S, " Car Fix Mut TOT");
else if (i > SIGNS+2 && i < SIGNS+7) {
k = i-(SIGNS+2)-1;
AnsiColor(elemansi[k]);
fprintf(S, " %c%c%c%3d %3d %3d %3d",
element[k][0], element[k][1], element[k][2],
elemode[k][0], elemode[k][1], elemode[k][2], elem[k]);
AnsiColor(DEFAULT);
} else if (i == SIGNS+7)
fprintf(S, " TOT %2d %3d %3d %3d", mo[0], mo[1], mo[2], count);
else if (i == OBJECTS)
PrintTab(' ', 23);
else if (i >= U_LO)
fprintf(S, " Uranian #%d", i-U_LO+1);
switch (i-SIGNS-1) {
case 1: fprintf(S, " +:%2d", pos); break;
case 2: fprintf(S, " -:%2d", count-pos); break;
case 3: fprintf(S, " M:%2d", abo); break;
case 4: fprintf(S, " N:%2d", count-abo); break;
case 5: fprintf(S, " A:%2d", lef); break;
case 6: fprintf(S, " D:%2d", count-lef); break;
case 7: fprintf(S, "<:%2d", lea); break;
}
printl();
}
/* Do another loop to print out the stars in their specified order. */
if (universe) for (i = S_LO; i <= S_HI; i++) if (!ignore[i]) {
j = BASE+starname[i-BASE];
AnsiColor(objectansi[j]);
fprintf(S, "%.4s: ", objectname[j]);
PrintZodiac(planet[j]);
fprintf(S, " ");
PrintAltitude(planetalt[j]);
k = inhouse[j];
AnsiColor(signansi(k));
fprintf(S, " [%2d%c%c house]", k, post[k][0], post[k][1]);
AnsiColor(DEFAULT);
fprintf(S, " ______ Star #%2d: %5.2f\n", i-BASE, starbright[j-BASE]);
}
}
/* Print out the aspect and midpoint grid for a chart, as specified with the */
/* -g switch. (Each grid row takes up 4 lines of text.) */
void ChartGrid()
{
int x, y, r, x1, y1, temp;
#ifdef INTERPRET
if (interpret) { /* Print interpretation instead if -I in effect. */
InterpretGrid();
return;
}
#endif
for (y1 = 0, y = 1; y <= total; y++) if (!ignore[y])
for (r = 1; r <= 4; r++) {
for (x1 = 0, x = 1; x <= total; x++) if (!ignore[x]) {
if (y1 > 0 && x1 > 0 && y+r > 2)
printc(r > 1 ? BOXV : BOXC);
if (r > 1) {
temp = grid->n[x][y];
/* Print aspect rows. */
if (x < y) {
if (temp);
AnsiColor(aspectansi[temp]);
if (r == 2)
fprintf(S, "%s", temp ? aspectabbrev[temp] : " ");
else if (!temp)
fprintf(S, " ");
else {
if (r == 3) {
if (grid->v[x][y] < 6000)
fprintf(S, "%c%2d", exdisplay & DASHga ?
(grid->v[x][y] < 0 ? 'a' : 's') :
(grid->v[x][y] < 0 ? '-' : '+'), abs(grid->v[x][y])/60);
else
fprintf(S, "%3d", abs(grid->v[x][y])/60);
} else
fprintf(S, "%02d'", abs(grid->v[x][y])%60);
}
/* Print midpoint rows. */
} else if (x > y) {
AnsiColor(signansi(temp));
if (r == 2) {
temp = grid->n[x][y];
fprintf(S, "%c%c%c", SIGNAM(temp));
} else if (r == 3) {
fprintf(S, "%2d%c", grid->v[x][y]/60, DEGR0);
} else
fprintf(S, "%02d'", grid->v[x][y]%60);
/* Print the diagonal of object names. */
} else {
AnsiColor(REVERSE);
if (r == 2) {
AnsiColor(objectansi[y]);
fprintf(S, "%c%c%c", OBJNAM(y));
} else {
temp = ZTOS(planet[y]);
AnsiColor(signansi(temp));
if (r == 3)
fprintf(S, "%2d%c", (int)planet[y] - (temp-1)*30, DEGR0);
else
fprintf(S, "%c%c%c", SIGNAM(temp));
}
}
AnsiColor(DEFAULT);
} else
if (y1 > 0)
PrintTab(BOXH, 3);
x1++;
if (column80 && x1 >= 20)
x = total;
}
if (y+r > 2)
printl();
y1++;
}
}
/* This is a subprocedure of DisplayGrands(). Here we print out one aspect */
/* configuration found by the parent procedure. */
void PrintGrand(nam, i1, i2, i3, i4)
char nam;
int i1, i2, i3, i4;
{
switch (nam) {
case '.': AnsiColor(aspectansi[_CON]); fprintf(S, "Stellium "); break;
case 't': AnsiColor(aspectansi[_TRI]); fprintf(S, "Grand Trine"); break;
case 's': AnsiColor(aspectansi[_OPP]); fprintf(S, "T-Square "); break;
case 'y': AnsiColor(aspectansi[_INC]); fprintf(S, "Yod "); break;
case 'g': AnsiColor(aspectansi[_SQU]); fprintf(S, "Grand Cross"); break;
case 'c': AnsiColor(aspectansi[_SEX]); fprintf(S, "Cradle "); break;
default: ;
}
AnsiColor(DEFAULT);
fprintf(S, " %s ", nam == '.' || nam == 't' || nam == 'g' ? "with" : "from");
AnsiColor(objectansi[i1]);
fprintf(S, "%c%c%c: ", OBJNAM(i1));
PrintZodiac(planet[i1]);
fprintf(S, " %s ", nam == '.' || nam == 't' ? "and" : "to ");
AnsiColor(objectansi[i2]);
fprintf(S, "%c%c%c: ", OBJNAM(i2));
PrintZodiac(planet[i2]);
fprintf(S, " %s ", nam == 'g' || nam == 'c' ? "to " : "and");
AnsiColor(objectansi[i3]);
fprintf(S, "%c%c%c: ", OBJNAM(i3));
PrintZodiac(planet[i3]);
if (nam == 'g' || nam == 'c') {
fprintf(S, " to ");
AnsiColor(objectansi[i4]);
fprintf(S, "%c%c%c: ", OBJNAM(i4));
PrintZodiac(planet[i4]);
}
printl();
}
/* Scan the aspect grid of a chart and print out any major configurations, */
/* as specified with the -g0 switch. */
void DisplayGrands()
{
int count = 0, i, j, k, l;
for (i = 1; i <= total; i++) if (!ignore[i])
for (j = 1; j <= total; j++) if (j != i && !ignore[j])
for (k = 1; k <= total; k++) if (k != i && k != j && !ignore[k]) {
/* Is there a Stellium among the current three planets? */
if (i < j && j < k && grid->n[i][j] == _CON &&
grid->n[i][k] == _CON && grid->n[j][k] == _CON) {
count++;
PrintGrand('.', i, j, k, l);
/* Is there a Grand Trine? */
} else if (i < j && j < k && grid->n[i][j] == _TRI &&
grid->n[i][k] == _TRI && grid->n[j][k] == _TRI) {
count++;
PrintGrand('t', i, j, k, l);
/* Is there a T-Square? */
} else if (j < k && grid->n[j][k] == _OPP &&
grid->n[MIN(i, j)][MAX(i, j)] == _SQU &&
grid->n[MIN(i, k)][MAX(i, k)] == _SQU) {
count++;
PrintGrand('s', i, j, k, l);
/* Is there a Yod? */
} else if (j < k && grid->n[j][k] == _SEX &&
grid->n[MIN(i, j)][MAX(i, j)] == _INC &&
grid->n[MIN(i, k)][MAX(i, k)] == _INC) {
count++;
PrintGrand('y', i, j, k, l);
}
for (l = 1; l <= total; l++) if (!ignore[l]) {
/* Is there a Grand Cross among the current four planets? */
if (i < j && i < k && i < l && j < l && grid->n[i][j] == _SQU &&
grid->n[MIN(j, k)][MAX(j, k)] == _SQU &&
grid->n[MIN(k, l)][MAX(k, l)] == _SQU &&
grid->n[i][l] == _SQU &&
MinDistance(planet[i], planet[k]) > 150.0 &&
MinDistance(planet[j], planet[l]) > 150.0) {
count++;
PrintGrand('g', i, j, k, l);
/* Is there a Cradle? */
} else if (i < l && grid->n[MIN(i, j)][MAX(i, j)] == _SEX &&
grid->n[MIN(j, k)][MAX(j, k)] == _SEX &&
grid->n[MIN(k, l)][MAX(k, l)] == _SEX &&
MinDistance(planet[i], planet[l]) > 150.0) {
count++;
PrintGrand('c', i, j, k, l);
}
}
}
if (!count)
fprintf(S, "No major configurations in aspect grid.\n");
}
/* This is subprocedure of ChartWheel(). Here we print out the location */
/* of a particular house cusp as well as what house cusp number it is. */
void PrintHouse(i, left)
int i, left;
{
if (!left)
PrintZodiac(house[i]);
AnsiColor(signansi(i));
fprintf(S, "<%d>", i);
if (left)
PrintZodiac(house[i]);
else
AnsiColor(DEFAULT);
}
/* Another subprocedure of ChartWheel(). Here we print out one line in a */
/* particular house cell (which may be blank). */
void PrintWheelSlot(obj, wheelcols)
int obj, wheelcols;
{
if (obj) {
AnsiColor(objectansi[obj]);
fprintf(S, " %c%c%c ", OBJNAM(obj)); /* Print planet and its position. */
PrintZodiac(planet[obj]);
fprintf(S, "%c ", ret[obj] < 0.0 ? 'r' : ' ');
PrintTab(' ', WHEELCOLS-14-1);
} else
PrintTab(' ', wheelcols-1); /* This particular line is blank. */
}
/* Display all the objects in a wheel format on the screen, as specified */
/* with the -w switch. The wheel is divided into the 12 houses and the */
/* planets are placed accordingly. */
void ChartWheel()
{
byte wheel[SIGNS][WHEELROWS];
int wheelcols, count = 0, i, j, k, l;
/* If the seconds (-b0) flag is set, we'll print all planet and house */
/* locations to the nearest zodiac second instead of just to the minute. */
seconds = -seconds;
wheelcols = WHEELCOLS + (seconds < 0)*4;
for (i = 0; i < SIGNS; i++)
for (j = 0; j < wheelrows; j++) /* Clear out array from the */
wheel[i][j] = 0; /* last time we used it. */
/* This section of code places each object in the wheel house array. */
for (i = 1; i <= total && count < wheelrows*12; i++) {
if (ignore[i] || !(i < _MC || i == OBJECTS || i > C_HI))
continue;
/* Try to put object in its proper house. If no room, */
/* then overflow over to the succeeding house. */
for (j = inhouse[i]-1; j < SIGNS; j = j < SIGNS ? (j+1)%SIGNS : j) {
/* Now try to find the proper place in the house to put the object. */
/* This is in sorted order, although a check is made for 0 Aries. */
if (wheel[j][wheelrows-1] > 0)
continue;
l = house[j+1] > house[Mod12(j+2)];
for (k = 0; wheel[j][k] > 0 &&
(planet[i] >= planet[wheel[j][k]] ||
(l && planet[i] < DEGHALF && planet[wheel[j][k]] > DEGHALF)) &&
!(l && planet[i] > DEGHALF && planet[wheel[j][k]] < DEGHALF); k++)
;
/* Actually insert object in proper place. */
if (wheel[j][k] <= 0)
wheel[j][k] = i;
else {
for (l = wheelrows-1; l > k; l--)
wheel[j][l] = wheel[j][l-1];
wheel[j][k] = i;
}
count++;
j = SIGNS;
}
}
/* Now, if this is really the -w switch and not -w0, then reverse the */
/* order of objects in western houses for more intuitive reading. */
if (!(exdisplay & DASHw0))
for (i = 3; i < 9; i++)
for (j = 0; j < wheelrows/2; j++) {
k = wheelrows-1-j;
l = wheel[i][j]; wheel[i][j] = wheel[i][k]; wheel[i][k] = l;
}
/* Here we actually print the wheel and the objects in it. */
printc(BOXNW); PrintTab(BOXH, WHEELCOLS-8); PrintHouse(11, TRUE);
PrintTab(BOXH, WHEELCOLS-11); PrintHouse(10, TRUE);
PrintTab(BOXH, WHEELCOLS-10); PrintHouse(9, TRUE);
PrintTab(BOXH, wheelcols-4); fprintf(S, "%c\n", BOXNE);
for (i = 0; i < wheelrows; i++) {
for (j = 10; j >= 7; j--) {
printc(BOXV); PrintWheelSlot(wheel[j][i], wheelcols);
}
fprintf(S, "%c\n", BOXV);
}
PrintHouse(12, TRUE); PrintTab(BOXH, WHEELCOLS-11);
printc(BOXC); PrintTab(BOXH, wheelcols-1); printc(BOXJN);
PrintTab(BOXH, wheelcols-1); printc(BOXC); PrintTab(BOXH, WHEELCOLS-10);
PrintHouse(8, FALSE); printl();
for (i = 0; i < wheelrows; i++) {
printc(BOXV); PrintWheelSlot(wheel[11][i], wheelcols); printc(BOXV);
/* For some rows, we have to insert the chart header information. */
if (i) {
PrintTab(' ', wheelcols-11-(i == 2 && !eurotime));
if (i == 1)
fprintf(S, "%s (%s) chart", appname, VERSION);
else if (i == 2) {
j = DayOfWeek(Mon, Day, Yea);
k = (int) (FRACT(dabs(Tim))*100.0+ROUND);
fprintf(S, "%c%c%c %s %s", DAYNAM(j), CharDate(Mon, Day, Yea, 2),
CharTime((int)floor(Tim), k));
} else if (i == 3) {
fprintf(S, "%c%02d:", Zon > 0.0 ? '-' : '+', (int)dabs(Zon));
j = (int) (FRACT(dabs(Zon))*100.0+ROUND);
fprintf(S, "%02d %s", j, CharLocation(Lon, Lat, 100.0));
} else
PrintTab(' ', 21);
PrintTab(' ', wheelcols-11-(i == 2 && !eurotime));
} else
PrintTab(' ', wheelcols*2-1);
printc(BOXV); PrintWheelSlot(wheel[6][i], wheelcols);
fprintf(S, "%c\n", BOXV);
}
PrintHouse(1, TRUE); PrintTab(BOXH, WHEELCOLS-10);
printc(BOXJW); PrintTab(' ', wheelcols-11);
fprintf(S, "%s", systemname[housesystem]);
PrintTab(' ', 14-StringLen(systemname[housesystem]));
fprintf(S, "Houses."); PrintTab(' ', wheelcols-11); printc(BOXJE);
PrintTab(BOXH, WHEELCOLS-10); PrintHouse(7, FALSE); printl();
for (i = 0; i < wheelrows; i++) {
printc(BOXV); PrintWheelSlot(wheel[0][i], wheelcols); printc(BOXV);
if (i == 0) {
PrintTab(' ', wheelcols-12);
fprintf(S, "Julian Day = %10.2f", JulianDayFromTime(T));
PrintTab(' ', wheelcols-12);
} else
PrintTab(' ', wheelcols*2-1);
printc(BOXV); PrintWheelSlot(wheel[5][i], wheelcols);
fprintf(S, "%c\n", BOXV);
}
PrintHouse(2, TRUE); PrintTab(BOXH, WHEELCOLS-10);
printc(BOXC); PrintTab(BOXH, wheelcols-1); printc(BOXJS);
PrintTab(BOXH, wheelcols-1); printc(BOXC);
PrintTab(BOXH, WHEELCOLS-10); PrintHouse(6, FALSE); printl();
for (i = 0; i < wheelrows; i++) {
for (j = 1; j <= 4; j++) {
printc(BOXV); PrintWheelSlot(wheel[j][i], wheelcols);
}
fprintf(S, "%c\n", BOXV);
}
printc(BOXSW); PrintTab(BOXH, wheelcols-4); PrintHouse(3, FALSE);
PrintTab(BOXH, WHEELCOLS-10); PrintHouse(4, FALSE);
PrintTab(BOXH, WHEELCOLS-10); PrintHouse(5, FALSE);
PrintTab(BOXH, WHEELCOLS-7); fprintf(S, "%c\n", BOXSE);
seconds = -seconds;
}
/* Display all aspects between objects in the chart, one per line, in */
/* sorted order based on the total "power" of the aspect, as specified with */
/* the -m0 switch. The same influences used for -I charts are used here. */
void ChartAspect()
{
int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
real ip, jp;
loop {
phi = -1;
/* Search for the next most powerful aspect in the aspect grid. */
for (i = 2; i <= total; i++) if (!ignore[i])
for (j = 1; j < i; j++) if (!ignore[j])
if (k = grid->n[j][i]) {
ip = i <= OBJECTS ? objectinf[i] : 2.5;
jp = j <= OBJECTS ? objectinf[j] : 2.5;
p = (int) (aspectinf[k]*(ip+jp)/2.0*
(1.0-dabs((real)(grid->v[j][i]))/60.0/aspectorb[k])*1000.0);
if ((p < pcut || (p == pcut && (i > icut ||
(i == icut && j > jcut)))) && p > phi) {
ihi = i; jhi = j; phi = p; ahi = k;
}
}
if (phi < 0) /* Exit when no less powerful aspect found. */
break;
pcut = phi; icut = ihi; jcut = jhi;
count++; /* Display the current aspect. */
#ifdef INTERPRET
if (interpret) { /* Interpret it if -I in effect. */
InterpretAspect(jhi, ihi);
continue;
}
#endif
fprintf(S, "%3d: ", count);
PrintAspect(jhi, ZTOS(planet[jhi]), (int)Sgn(ret[jhi]), ahi,
ihi, ZTOS(planet[ihi]), (int)Sgn(ret[ihi]), 'a');
k = grid->v[jhi][ihi];
AnsiColor(k < 0 ? WHITE : LTGRAY);
fprintf(S, " - orb: %c%d%c%02d'",
exdisplay & DASHga ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
abs(k)/60, DEGR1, abs(k)%60);
AnsiColor(DKGREEN);
fprintf(S, " - power:%6.2f\n", (real) phi/1000.0);
AnsiColor(DEFAULT);
}
}
/* Display locations of all midpoints between objects in the chart, */
/* one per line, in sorted zodiac order from zero Aries onward, as */
/* specified with the -m switch. */
void ChartMidpoint()
{
int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
loop {
mlo = 21600;
/* Search for the next closest midpoint farther down in the zodiac. */
for (i = 1; i < total; i++) if (!ignore[i])
for (j = i+1; j <= total; j++) if (!ignore[j]) {
m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
if ((m > mcut || (m == mcut && (i > icut ||
(i == icut && j > jcut)))) && m < mlo) {
ilo = i; jlo = j; mlo = m;
}
}
if (mlo >= 21600) /* Exit when no midpoint farther in zodiac found. */
break;
mcut = mlo; icut = ilo; jcut = jlo;
count++; /* Display the current midpoint. */
#ifdef INTERPRET
if (interpret) { /* Interpret it if -I in effect. */
InterpretMidpoint(ilo, jlo);
continue;
}
#endif
fprintf(S, "%4d: ", count);
PrintZodiac((real) mlo/60.0);
printc(' ');
PrintAspect(ilo, ZTOS(planet[ilo]), (int)Sgn(ret[ilo]), 0,
jlo, ZTOS(planet[jlo]), (int)Sgn(ret[jlo]), 'm');
AnsiColor(DEFAULT);
m = (int)(MinDistance(planet[ilo], planet[jlo])*60.0);
fprintf(S, "-%4d%c%02d' degree span.\n", m/60, DEGR1, m%60);
}
}
/* Display locations of the objects on the screen with respect to the local */
/* horizon, as specified with the -Z switch. */
void ChartHorizon()
{
real lon, lat, sx, sy, vx, vy,
lonz[TOTAL+1], latz[TOTAL+1], azi[TOTAL+1], alt[TOTAL+1];
int prime, i, j, k, tot;
/* Set up some initial variables. */
prime = (exdisplay & DASHZ0) > 0;
lon = DTOR(Mod(Lon)); lat = DTOR(Lat);
tot = universe ? total : BASE;
/* First find zenith location on Earth of each object. */
for (i = 1; i <= tot; i++) {
lonz[i] = DTOR(planet[i]); latz[i] = DTOR(planetalt[i]);
EclToEqu(&lonz[i], &latz[i]);
}
/* Then, convert this to local horizon altitude and azimuth. */
for (i = 1; i <= tot; i++) if (i != _MC) {
lonz[i] = DTOR(Mod(RTOD(lonz[_MC]-lonz[i]+lon)));
lonz[i] = DTOR(Mod(RTOD(lonz[i]-lon+PI/2.0)));
EquToLocal(&lonz[i], &latz[i], PI/2.0-lat);
azi[i] = DEGREES-RTOD(lonz[i]); alt[i] = RTOD(latz[i]);
}
/* If the -Z0 switch flag is in effect, convert from altitude/azimuth */
/* coordinates to prime vertical coordinates that we'll print instead. */
if (prime) {
for (i = 1; i <= tot; i++) {
azi[i] = DTOR(azi[i]); alt[i] = DTOR(alt[i]);
CoorXform(&azi[i], &alt[i], PI/2.0);
azi[i] = RTOD(azi[i]); alt[i] = RTOD(alt[i]);
}
}
/* Now, actually print the location of each object. */
fprintf(S,
"Body Altitude Azimuth Azi. Vector %s Vector Moon Vector\n\n",
centerplanet ? " Sun" : " Earth");
for (k = 1; k <= tot; k++) {
i = k <= BASE ? k : BASE+starname[k-BASE];
if (ignore[i] || !IsThing(i))
continue;
AnsiColor(objectansi[i]);
fprintf(S, "%-4.4s: ", objectname[i]);
PrintAltitude(alt[i]);
/* Determine directional vector based on azimuth. */
j = (int) (FRACT(azi[i])*60.0);
fprintf(S, " %3d%c%02d'", (int) azi[i], DEGR1, j);
sx = cos(DTOR(azi[i])); sy = sin(DTOR(azi[i]));
if (dabs(sx) < dabs(sy)) {
vx = dabs(sx / sy); vy = 1.0;
} else {
vy = dabs(sy / sx); vx = 1.0;
}
fprintf(S, " (%.2f%c", vy,
sy < 0.0 ? (prime ? 'u' : 's') : (prime ? 'd' : 'n'));
fprintf(S, " %.2f%c)", vx,
sx > 0.0 ? 'e' : 'w');
/* Determine distance vector of current object from Sun and Moon. */
vx = azi[1]-azi[i]; vy = azi[2]-azi[i];
fprintf(S, " [%6.1f%6.1f] [%6.1f%6.1f]",
dabs(vx) < DEGHALF ? vx : Sgn(vx)*(DEGREES-dabs(vx)), alt[1]-alt[i],
dabs(vy) < DEGHALF ? vy : Sgn(vy)*(DEGREES-dabs(vy)), alt[2]-alt[i]);
if (i >= U_LO) {
if (i <= U_HI)
fprintf(S, " Uranian #%d", i-U_LO+1);
else
fprintf(S, " Star #%2d", i-S_LO+1);
}
printl();
}
AnsiColor(DEFAULT);
}
/* Display x,y,z locations of each body (in AU) with respect to the Sun */
/* (or whatever the specified center planet is), as in the -S switch. */
/* These values were already determined when calculating the planet */
/* positions themselves, so this procedure is basically just a loop. */
void ChartSpace()
{
real x, y, z;
int i;
fprintf(S, "Body Angle X axis Y axis Z axis Length\n");
for (i = 0; i <= BASE; i++) {
if (ignore[i] || (i == _MOO && !placalc) || !IsObject(i))
continue;
AnsiColor(objectansi[i]);
fprintf(S, "%c%c%c%c: ", OBJNAM(i),
objectname[i][3] ? objectname[i][3] : ' ');
x = spacex[i]; y = spacey[i]; z = spacez[i];
fprintf(S, "[%7.2f] [%7.3f] [%7.3f] [%7.3f] [%7.3f]",
planet[i], x, y, z, sqrt(x*x+y*y+z*z));
if (i >= U_LO) {
if (i <= U_HI)
fprintf(S, " Uranian #%d", i-U_LO+1);
else
fprintf(S, " Star #%2d", i-S_LO+1);
}
printl();
}
AnsiColor(DEFAULT);
}
/* Print the locations of the astro-graph lines on the Earth as specified */
/* with the -L switch. This includes Midheaven and Nadir lines, zenith */
/* positions, and locations of Ascendant and Descendant lines. */
void ChartAstroGraph()
{
crosstruct PTR c;
real planet1[TOTAL+1], planet2[TOTAL+1], mc[TOTAL+1], ic[TOTAL+1],
as[TOTAL+1], ds[TOTAL+1], as1[TOTAL+1], ds1[TOTAL+1],
lo = Lon, longm, w, x, y, z, ad, oa, am, od, dm;
int occurcount = 0, tot = total, i, j, k, l, m, n;
if (exdisplay & DASHL0)
{
Allocate(c, sizeof(crosstruct), crosstruct PTR);
if (c == NULL
#ifdef PC
/* For PC's the array better not cross a segment boundary. */
|| HIWORD(LOWORD(c) + sizeof(crosstruct)) > 0
#endif
) {
PrintError("Not enough memory for crossing table.");
return;
}
}
#ifdef MATRIX
for (i = 1; i <= total; i++) {
planet1[i] = DTOR(planet[i]);
planet2[i] = DTOR(planetalt[i]); /* Calculate zenith location on */
EclToEqu(&planet1[i], &planet2[i]); /* Earth of each object. */
}
/* Print header. */
fprintf(S, "Object :");
for (j = 0, i = 1; i <= total; i++)
if (!ignore[i] && IsThing(i)) {
AnsiColor(objectansi[i]);
fprintf(S, " %c%c%c", OBJNAM(i));
j++;
if (column80 && j >= 17) {
tot = i;
i = total;
}
}
AnsiColor(DEFAULT);
fprintf(S, "\n------ :");
for (i = 1; i <= tot; i++)
if (!ignore[i] && IsThing(i))
fprintf(S, " ###");
/* Print the longitude locations of the Midheaven lines. */
fprintf(S, "\nMidheav: ");
if (lo < 0.0)
lo += DEGREES;
for (i = 1; i <= tot; i++)
if (!ignore[i] && IsThing(i)) {
AnsiColor(objectansi[i]);
x = DTOR(MC)-planet1[i];
if (x < 0.0)
x += 2.0*PI;
if (x > PI)
x -= 2.0*PI;
z = lo+RTOD(x);
if (z > DEGHALF)
z -= DEGREES;
mc[i] = z;
fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
}
AnsiColor(DEFAULT);
/* The Nadir lines are just always 180 degrees away from the Midheaven. */
fprintf(S, "\nNadir : ");
for (i = 1; i <= tot; i++)
if (!ignore[i] && IsThing(i)) {
AnsiColor(objectansi[i]);
z = mc[i] + DEGHALF;
if (z > DEGHALF)
z -= DEGREES;
ic[i] = z;
fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
}
AnsiColor(DEFAULT);
/* Print the Zenith latitude locations. */
fprintf(S, "\nZenith : ");
for (i = 1; i <= tot; i++)
if (!ignore[i] && IsThing(i)) {
AnsiColor(objectansi[i]);
y = RTOD(planet2[i]);
fprintf(S, "%3.0f%c", dabs(y), y < 0.0 ? 's' : 'n');
as[i] = ds[i] = as1[i] = ds1[i] = LARGE;
}
printl2();
/* Now print the locations of Ascendant and Descendant lines. Since these */
/* are curvy, we loop through the latitudes, and for each object at each */
/* latitude, print the longitude location of the line in question. */
longm = DTOR(Mod(MC+lo));
for (j = 80; j >= -80; j -= graphstep) {
AnsiColor(DEFAULT);
fprintf(S, "Asc@%2d%c: ", j >= 0 ? j : -j, j < 0 ? 's' : 'n');
for (i = 1; i <= tot; i++)
if (!ignore[i] && IsThing(i)) {
AnsiColor(objectansi[i]);
ad = tan(planet2[i])*tan(DTOR(j));
if (ad*ad > 1.0) {
fprintf(S, " -- ");
as1[i] = ds1[i] = ret2[i] = 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;
as1[i] = as[i];
as[i] = z = RTOD(z);
ret2[i] = ad;
fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
}
}
/* Again, the Descendant position is related to the Ascendant's, */
/* being a mirror image, so it can be calculated somewhat easier. */
AnsiColor(DEFAULT);
fprintf(S, "\nDsc@%2d%c: ", j >= 0 ? j : -j, j < 0 ? 's' : 'n');
for (i = 1; i <= tot; i++)
if (!ignore[i] && IsThing(i)) {
AnsiColor(objectansi[i]);
ad = ret2[i];
if (ad == LARGE)
fprintf(S, " -- ");
else {
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;
ds1[i] = ds[i];
ds[i] = z = RTOD(z);
fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
}
}
printl();
#endif /* MATRIX */
/* Now, if the -L0 switch is in effect, then take these line positions, */
/* which we saved in an array above as we were printing them, and */
/* calculate and print the latitude crossings. */
if (exdisplay & DASHL0)
for (l = 1; l <= total; l++) if (!ignore[l] && IsThing(l))
for (k = 1; k <= total; k++) {
if (ignore[k] || !IsThing(k))
continue;
for (n = 0; n <= 1; n++) {
x = n ? ds1[l] : as1[l];
y = n ? ds[l] : as[l];
for (m = 0; m <= 1; m++) {
/* Check if Ascendant/Descendant cross Midheaven/Nadir. */
z = m ? ic[k] : mc[k];
if (occurcount < MAXCROSS &&
dabs(x-y) < DEGHALF && Sgn(z-x) != Sgn(z-y)) {
c->obj1[occurcount] = n ? -l : l;
c->obj2[occurcount] = m ? -k : k;
c->lat[occurcount] = (real)j+5.0*dabs(z-y)/dabs(x-y);
c->lon[occurcount] = z;
occurcount++;
}
/* Check if Ascendant/Descendant cross another Asc/Des. */
w = m ? ds1[k] : as1[k];
z = m ? ds[k] : as[k];
if (occurcount < MAXCROSS && k > l &&
dabs(x-y)+dabs(w-z) < DEGHALF && Sgn(w-x) != Sgn(z-y)) {
c->obj1[occurcount] = n ? -l : l;
c->obj2[occurcount] = 100+(m ? -k : k);
c->lat[occurcount] = (real)j+5.0*
dabs(y-z)/(dabs(x-w)+dabs(y-z));
c->lon[occurcount] = MIN(x, y)+dabs(x-y)*
dabs(y-z)/(dabs(x-w)+dabs(y-z));
occurcount++;
}
}
}
}
}
if ((exdisplay & DASHL0) == 0)
return;
printl();
/* Now, print out all the latitude crossings we found. */
/* First, we sort them in order of decreasing latitude. */
for (i = 1; i < occurcount; i++) {
j = i-1;
while (j >= 0 && c->lat[j] < c->lat[j+1]) {
SWAP(c->obj1[j], c->obj1[j+1]); SWAP(c->obj2[j], c->obj2[j+1]);
SwapReal(&c->lat[j], &c->lat[j+1]); SwapReal(&c->lon[j], &c->lon[j+1]);
j--;
}
}
for (i = 1; i < occurcount; i++) {
j = abs(c->obj1[i]);
AnsiColor(objectansi[j]);
fprintf(S, "%c%c%c ", OBJNAM(j));
AnsiColor(elemansi[c->obj1[i] > 0 ? _FIR : _AIR]);
fprintf(S, "%s ", c->obj1[i] > 0 ? "Ascendant " : "Descendant");
AnsiColor(WHITE);
fprintf(S, "crosses ");
j = abs(c->obj2[i] - (c->obj2[i] < 50 ? 0 : 100));
AnsiColor(objectansi[j]);
fprintf(S, "%c%c%c ", OBJNAM(j));
AnsiColor(elemansi[c->obj2[i] < 50 ?
(c->obj2[i] > 0 ? _EAR : _WAT) : (c->obj2[i] > 100 ? _FIR : _AIR)]);
fprintf(S, "%s ", c->obj2[i] < 50 ? (c->obj2[i] > 0 ? "Midheaven " :
"Nadir ") : (c->obj2[i] > 100 ? "Ascendant " : "Descendant"));
j = (int) (FRACT(dabs(c->lon[i]))*60.0);
AnsiColor(DEFAULT);
fprintf(S, "at %3d%c%02d'%c, ", (int) dabs(c->lon[i]), DEGR1,
j, c->lon[i] < 0.0 ? 'E' : 'W');
j = (int) (FRACT(dabs(c->lat[i]))*60.0);
fprintf(S, "%2d%c%02d'%c\n", (int) dabs(c->lat[i]), DEGR1,
j, c->lat[i] < 0.0 ? 'S' : 'N');
}
Deallocate(c);
if (!occurcount) {
AnsiColor(DEFAULT);
fprintf(S, "No latitude crossings.\n");
}
}
/* charts.c */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.