⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xoptions.c

📁 占星术4.0源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
** Astrolog (Version 4.00) File: xoptions.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

/*
******************************************************************************
** Chart Graphics Subroutines.
******************************************************************************
*/

/* Return whether the specified object should be displayed in the current  */
/* graphics chart type. For example, don't include the Moon in the solar   */
/* system charts, don't include house cusps in astro-graph, and so on.     */

int Proper(i)
int i;
{
  int j;

  if (modex == MODEL || modex == MODEE)       /* astro-graph or ephem charts */
    j = IsThing(i);
  else if (modex == MODEZ || modex == MODEG)  /* horizon or zenith charts */
    j = IsObject(i);
  else if (modex == MODES)                    /* solar system charts */
    j = (i != _MOO && IsObject(i));
  else
    j = TRUE;
  return j && !ignore[i];                     /* check restriction status */
}


/* Set up arrays with the sine and cosine values of each degree. This is   */
/* used by the wheel chart routines which draw lots of circles. Memory is  */
/* allocated for this array if not already done. The allocation and        */
/* initialization is only done once, the first time the routine is called. */

bool InitCircle()
{
  char string[STRING];
  int i;

  if (circ != NULL)
    return TRUE;
  Allocate(circ, sizeof(circlestruct), circlestruct PTR);
  if (circ == NULL
#ifdef PC
    /* For PC's the array better not cross a segment boundary. */
    || HIWORD(LOWORD(circ) + sizeof(circlestruct)) > 0
#endif
    ) {
    sprintf(string, "Not enough memory for sine table (%d bytes).",
      sizeof(circlestruct));
    PrintError(string);
    return FALSE;
  }
  for (i = 0; i < DEGR; i++) {
    circ->x[i] = COSD((real) i);
    circ->y[i] = SIND((real) i);
  }
  circ->x[DEGR] = circ->x[0]; circ->y[DEGR] = circ->y[0];
  return TRUE;
}


/* Adjust an array of zodiac positions so that no two positions are within   */
/* a certain orb of each other. This is used by the wheel drawing chart      */
/* routines in order to make sure that we don't draw any planet glyphs on    */
/* top of each other. We'll later draw the glyphs at the adjusted positions. */

void FillSymbolRing(symbol)
real *symbol;
{
  real orb = DEFORB*256.0/(real)charty*(real)SCALE, k1, k2, temp;
  int i, j, k = 1, l;

  /* Keep adjusting as long as we can still make changes, or until we do 'n' */
  /* rounds. (With many objects, there just may not be enough room for all.) */

  for (l = 0; k && l < divisions*2; l++) {
    k = 0;
    for (i = 1; i <= total; i++) if (Proper(i)) {

      /* For each object, determine who is closest on either side. */

      k1 = LARGE; k2 = -LARGE;
      for (j = 1; j <= total; j++)
        if (Proper(j) && i != j) {
          temp = symbol[j]-symbol[i];
          if (dabs(temp) > DEGHALF)
            temp -= DEGREES*Sgn(temp);
          if (temp < k1 && temp >= 0.0)
            k1 = temp;
          else if (temp > k2 && temp <= 0.0)
            k2 = temp;
        }

      /* If an object's too close on one side, then we move to the other. */

      if (k2 > -orb && k1 > orb) {
        k = 1; symbol[i] = Mod(symbol[i]+orb*0.51+k2*0.49);
      } else if (k1 < orb && k2 < -orb) {
        k = 1; symbol[i] = Mod(symbol[i]-orb*0.51+k1*0.49);

      /* If we are bracketed by close objects on both sides, then let's move */
      /* to the midpoint, so we are as far away as possible from either one. */

      } else if (k2 > -orb && k1 < orb) {
        k = 1; symbol[i] = Mod(symbol[i]+(k1+k2)*0.5);
      }
    }
  }
}


/* Adjust an array of longitude positions so that no two are within a    */
/* certain orb of each other. This is used by the astro-graph routine to */
/* make sure we don't draw any planet glyphs marking the lines on top of */
/* each other. This is almost identical to the FillSymbolRing() routine  */
/* used by the wheel charts; however, there the glyphs are placed in a   */
/* continuous ring, while here we have the left and right screen edges.  */
/* Also, here we are placing two sets of planets at the same time.       */

void FillSymbolLine(symbol)
real *symbol;
{
  real orb = DEFORB*1.35*(real)SCALE, max = DEGREES, k1, k2, temp;
  int i, j, k = 1, l;

  if (modex != MODEE)
    max *= (real)SCALE;
  else
    orb *= DEGREES/(real)chartx;

  /* Keep adjusting as long as we can still make changes. */

  for (l = 0; k && l < divisions*2; l++) {
    k = 0;
    for (i = 1; i <= total*2; i++)
      if (Proper((i+1)/2) && symbol[i] >= 0.0) {

        /* For each object, determine who is closest to the left and right. */

        k1 = max-symbol[i]; k2 = -symbol[i];
        for (j = 1; j <= total*2; j++) {
          if (Proper((j+1)/2) && i != j) {
            temp = symbol[j]-symbol[i];
            if (temp < k1 && temp >= 0.0)
              k1 = temp;
            else if (temp > k2 && temp <= 0.0)
              k2 = temp;
          }
        }

        /* If an object's too close on one side, then we move to the other. */

        if (k2 > -orb && k1 > orb) {
          k = 1; symbol[i] = symbol[i]+orb*0.51+k2*0.49;
        } else if (k1 < orb && k2 < -orb) {
          k = 1; symbol[i] = symbol[i]-orb*0.51+k1*0.49;
        } else if (k2 > -orb && k1 < orb) {
          k = 1; symbol[i] = symbol[i]+(k1+k2)*0.5;
        }
      }
  }
}


/* Another stream reader, this one is used by the globe drawing routine: */
/* for the next body of land/water, return its name (and color), its     */
/* longitude and latitude, and a vector description of its outline.      */

int ReadWorldData(nam, loc, lin)
char **nam, **loc, **lin;
{
  static char FAR **datapointer = worlddata;

  *loc = *datapointer++;
  *lin = *datapointer++;
  *nam = *datapointer++;
  if (*loc[0]) {
    if ((exdisplay & DASHXP0) && xfile)
      fprintf(stdout, "%s\n", *nam+1);
    return TRUE;
  }
  datapointer = worlddata;    /* Reset stream when no data left. */
  return FALSE;
}


/* Given longitude and latitude values on a globe, return the window        */
/* coordinates corresponding to them. In other words, project the globe     */
/* onto the view plane, and return where our coordinates got projected to,  */
/* as well as whether our location is hidden on the back side of the globe. */

int GlobeCalc(x1, y1, u, v, cx, cy, rx, ry, deg)
real x1, y1;
int *u, *v, cx, cy, rx, ry, deg;
{
  real j, siny1;

  /* Compute coordinates for a general globe invoked with -XG switch. */

  if (modex == MODEG) {
    x1 = Mod(x1+(real)deg);    /* Shift by current globe rotation value. */
    if (tilt != 0.0) {
      x1 = DTOR(x1); y1 = DTOR(DEGQUAD-y1);       /* Do another coordinate  */
      CoorXform(&x1, &y1, tilt / DEGRAD);         /* shift if the globe's   */
      x1 = Mod(RTOD(x1)); y1 = DEGQUAD-RTOD(y1);  /* equator is tilted any. */
    }
    *v = cy + (int) ((real)ry*-COSD(y1)-ROUND);
    *u = cx + (int) ((real)rx*-COSD(x1)*SIND(y1)-ROUND);
    return x1 > DEGHALF;
  }

  /* Compute coordinates for a polar globe invoked with -XP switch. */

  siny1 = SIND(y1);
  j = xbonus ? DEGQUAD+x1+deg : 270.0-x1-deg;
  *v = cy + (int) (siny1*(real)ry*SIND(j)-ROUND);
  *u = cx + (int) (siny1*(real)rx*COSD(j)-ROUND);
  return xbonus ? y1 < DEGQUAD : y1 > DEGQUAD;
}


/* Draw a globe in the window, based on the specified rotational and tilt  */
/* values. In addition, we may draw in each planet at its zenith position. */

void DrawGlobe(deg)
int deg;
{
  char *nam, *loc, *lin, d;
  int X[TOTAL+1], Y[TOTAL+1], M[TOTAL+1], N[TOTAL+1],
    cx = chartx/2, cy = charty/2, rx, ry, lon, lat, unit = 12*SCALE,
    x, y, m, n, u, v, i, J, k, l, o;
  real planet1[TOTAL+1], planet2[TOTAL+1], x1, y1, j;
  colpal c;

  rx = cx-1; ry = cy-1;

  /* Loop through each coastline string, drawing visible parts on the globe. */

  while (ReadWorldData(&nam, &loc, &lin)) {
    i = nam[0]-'0';
    c = (modex == MODEG && xbonus) ? gray :
      (i ? rainbowcolor[i] : maincolor[6]);
    DrawColor(c);

    /* Get starting longitude and latitude of current coastline piece. */

    lon = (loc[0] == '+' ? 1 : -1)*
      ((loc[1]-'0')*100 + (loc[2]-'0')*10 + (loc[3]-'0'));
    lat = (loc[4] == '+' ? 1 : -1)*((loc[5]-'0')*10 + (loc[6]-'0'));
    x = 180-lon;
    y = 90-lat;
    GlobeCalc((real) x, (real) y, &m, &n, cx, cy, rx, ry, deg);

    /* Go down the coastline piece, drawing each visible segment on globe. */

    o = (tilt == 0.0 && modex != MODEP);
    k = l = TRUE;
    while (d = *lin++) {
      if (d == 'L' || d == 'H' || d == 'G')
        x--;
      else if (d == 'R' || d == 'E' || d == 'F')
        x++;
      if (d == 'U' || d == 'H' || d == 'E')
        y--;
      else if (d == 'D' || d == 'G' || d == 'F')
        y++;
      if (x > 359)
        x = 0;
      else if (x < 0)
        x = 359;
      if (o) {
        k = x+deg;
        if (k > 359)
          k -= DEGR;
        k = (k <= 180);
      }
      if (k && !GlobeCalc((real) x, (real) y, &u, &v, cx, cy, rx, ry, deg)) {
        if (l)
          DrawLine(m, n, u, v);
        m = u; n = v;
        l = TRUE;
      } else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -