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.