ftp.nice.ch/pub/next/science/physics/Moon.NIHS.bs.tar.gz#/Moon/Source/shadow.c

This is shadow.c in view mode; [Download] [Up]

/* shadow.c
 * Part of the Moon application for the NeXT computer.
 * Author:  Geoffrey S. Knauth
 * Date:    January 4, 1992
 *
 * Permission to copy this program is hereby granted under the terms
 * of the Free Software Foundation's GNU General Public License.
 */

#import <dpsclient/event.h>		/* NXPoint */
#import <dpsclient/psops.h>		/* PSsetgray */
#import "all.h"

void DrawMoonShadow		/* draw moon shadow, independent of view */
   (float phase,		/* phase of the moon */
    NXPoint *center,		/* pixel center of moon */
    float xradius,		/* half width of moon in pixels */
    float yradius,		/* half height of moon in pixels */
    int shadowColor)		/* color to use in drawing shadow */
{
  /* DrawMoonShadow is called from within drawSelf:: methods of various
   * view types.  Postscript focus locking and unlocking are outside
   * of this function.
   */
    float yDown, yUp;
    int i, up, down, oneSideHalf, numLeftSidePoints, numRightSidePoints;
    NXPoint *leftSide, *rightSide;	/* storage for lists of NXPoints */
    double d, amp, xscale;

  /* the number of points in the top half on one side is
   *	oneSideHalf = center+1..top,
   *	= (top - (center+1) + 1), or (top - center);
   */
    oneSideHalf = rint(yradius);

  /* make sure oneSideHalf is >= 0 */
    if (oneSideHalf < 0) oneSideHalf = 0;

  /* calculate the number of points on each side
   * remember to add a point for the center
   */
    numLeftSidePoints = numRightSidePoints = 1 + 2 * oneSideHalf;

  /* allocate the points */
    leftSide = calloc(numLeftSidePoints, sizeof(NXPoint));
    rightSide = calloc(numRightSidePoints, sizeof(NXPoint));

  /* Now iterate from the center to the bottom, filling in information
   *	for the left and right sides.
   * Remember to calculate the region to black out, not whiten.
   * As we fill in points for the bottom half, we know that the points
   *  for the top half will be a mirror image, so we can just copy them.
   */
    xscale = cos(2 * PI * phase);
    for (i = 0,				/* variable controlling loop */
	 down = oneSideHalf,		/* index into arrays of NXPoint */
	 yDown = yUp = center->y;	/* diverging y values for halves */
	 i <= oneSideHalf;		/* stop when bottom half done */
	 i++,				/* 0..oneSideHalf-1 */
	 down++,			/* oneSideHalf..bottom index */
	 yDown -= 1.,			/* float y for drawing bottom half */
	 yUp += 1.)			/* float y for drawing upper half */
    {
	if ((d = i / yradius) > 1.0)
	    d = 1.0;
	amp = xradius * cos(asin(d));	/* d > 1.0 yields NaN (not a number) */

	/* 0.0 = new moon, 0.5 full moon, 1.0 = next new moon */
	if (phase < 0.5) {					/* waxing */
	    leftSide[down].x  = center->x - amp;
	    rightSide[down].x = center->x + xscale * amp;
	} else {						/* waning */
	    rightSide[down].x = center->x + amp;
	    leftSide[down].x  = center->x - xscale * amp;
	}
	leftSide[down].y = rightSide[down].y = yDown;

	if (i) {		/* # points offset downward from center */
	    up = down - 2 * i;
	    leftSide[up].x  = leftSide[down].x;
	    rightSide[up].x = rightSide[down].x;
	    leftSide[up].y = rightSide[up].y = yUp;
	}
    }

  /* Now iterate again from the top, this time actually creating
   *	a path clockwise around the points just calculated.
   */
    PSnewpath();
    PSmoveto(rightSide[0].x, rightSide[0].y);

  /* Go down the right side, starting with the second point, because we
   * just moved to the top point.
   */
    for (i = 1; i < numRightSidePoints; i++)
	PSlineto(rightSide[i].x, rightSide[i].y);

  /* Now go up the left side, starting again with the second point, because
   * we just reached the bottom, and stop one short of the top, because we
   * started with the top when we started down in the first place.
   */
    for (i = numLeftSidePoints - 2; i > 0; i--)
	PSlineto(leftSide[i].x, leftSide[i].y);

    PSclosepath();

  /* draw the moon shadow, that part of the moon hidden from the sun */
    PSsetgray(shadowColor);
    PSfill();

  /* deallocate the points */
    free((char *) leftSide);
    free((char *) rightSide);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.