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.