[comp.sources.misc] v15i025: Graphics Gems, Part 3/5

craig@weedeater.math.yale.edu (Craig Kolb) (10/15/90)

Posting-number: Volume 15, Issue 25
Submitted-by: Craig Kolb <craig@weedeater.math.yale.edu>
Archive-name: ggems/part03

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 5)."
# Contents:  AALines/utah.c Albers.c BoundSphere.c Dissolve.c
#   DoubleLine.c GraphicsGems.h LineEdge.c MatrixInvert.c
#   PolyScan/poly_clip.c PolyScan/poly_scan.c Roots3And4.c
# Wrapped by craig@weedeater on Fri Oct 12 15:53:13 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'AALines/utah.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'AALines/utah.c'\"
else
echo shar: Extracting \"'AALines/utah.c'\" \(4532 characters\)
sed "s/^X//" >'AALines/utah.c' <<'END_OF_FILE'
X/*
X	file:		utah.c
X	description:	interface to Utah RLE toolkit
X	author:		A. T. Campbell
X	date:		October 27, 1989
X*/
X
X#ifndef lint
Xstatic char	sccsid[] = "%W% %G%";		/* SCCS info */
X#endif lint
X	
X#include <math.h>
X#include <stdio.h>
X#ifdef sequent
X#include <strings.h>
X#else
X#include <string.h>
X#endif
X#include "utah.h"
X
X/******************************************************************************/
X
X/* return values */
Xextern void	free();
Xextern char	*malloc();
X
X/******************************************************************************/
X
Xutah_read_close(ufp)
XUTAH_FILE	*ufp;
X{
X	return(0);
X}
X
X/******************************************************************************/
X
XUTAH_FILE *
Xutah_read_init(fname, ht, wd)
X
Xchar	*fname;
Xint	*ht, *wd;
X{
X	FILE		*fp;
X	UTAH_FILE	*ufp;
X
X	/* open output stream */
X	if (!strcmp(fname, ""))
X		fp = stdin;
X	else {
X		if ((fp = fopen(fname, "r")) == NULL)
X		return(NULL);
X	}
X
X 	/* change the default sv_globals struct to match what we need */
X	ufp = (UTAH_FILE *) malloc(sizeof(UTAH_FILE));
X	*ufp = sv_globals;
X	ufp->svfb_fd = fp;
X
X	/* read the header in the input file */
X  	if (rle_get_setup(ufp) != 0)
X		return(NULL);
X
X	/* get image size */
X	*wd = ufp->sv_xmax - ufp->sv_xmin + 1;
X	*ht = ufp->sv_ymax - ufp->sv_ymin + 1;
X
X	/* normal termination */
X	return(ufp);
X}
X
X/******************************************************************************/
X
Xutah_read_pixels(ufp, pixels)
X
XUTAH_FILE 	*ufp;
Xunsigned char	pixels[][3];
X{
X	static unsigned	n = 0;
X	static unsigned char	*r = NULL, *g = NULL, *b = NULL;
X	int		i, width;
X
X	/* allocate storage */
X	width = ufp->sv_xmax + 1;
X	if (width > n) {
X		if (n > 0) {
X			free((char *)r);
X			free((char *)g);
X			free((char *)b);
X		}
X		n = width;
X		r = (unsigned char *) malloc(n * sizeof(unsigned char));
X		g = (unsigned char *) malloc(n * sizeof(unsigned char));
X		b = (unsigned char *) malloc(n * sizeof(unsigned char));
X	}
X
X	/* read this row */
X	utah_read_rgb(ufp, r, g, b);
X
X	/* convert to pixels */
X	for (i = 0; i < width; i++) {
X		pixels[i][0] = r[i];
X		pixels[i][1] = g[i];
X		pixels[i][2] = b[i];
X	}
X
X	return(0);
X}
X
X/******************************************************************************/
X
Xutah_read_rgb(ufp, r, g, b)
X
XUTAH_FILE	*ufp;
Xunsigned char	r[], g[], b[];
X{
X	rle_pixel	*rows[3];
X
X	/* set color channels */
X	rows[0] = r;
X	rows[1] = g;
X	rows[2] = b;
X
X	/* read this row */
X	rle_getrow(ufp, rows);
X	return(0);
X}
X
X/******************************************************************************/
X
Xutah_write_close(ufp)
X
XUTAH_FILE	*ufp;
X{
X	if (!ufp) return(-1);
X	sv_puteof(ufp);
X	return(0);
X}
X
X/******************************************************************************/
X
XUTAH_FILE *
Xutah_write_init(fname, ht, wd)
X
Xchar	*fname;
Xint	ht, wd;
X{
X	FILE		*fp;
X	UTAH_FILE	*ufp;
X
X	/* open output stream */
X	if (!strcmp(fname, ""))
X		fp = stdout;
X	else {
X		if ((fp = fopen(fname, "w")) == NULL)
X		return(NULL);
X	}
X
X 	/* change the default sv_globals struct to match what we need */
X	ufp = (UTAH_FILE *) malloc(sizeof(UTAH_FILE));
X	*ufp = sv_globals;
X	ufp->svfb_fd = fp;
X	ufp->sv_xmax = wd - 1;
X	ufp->sv_ymax = ht - 1;
X	ufp->sv_alpha = 0;	/* No coverage (alpha) */
X
X	/* create the header in the output file */
X  	sv_setup(RUN_DISPATCH, ufp);
X
X	/* normal termination */
X	return(ufp);
X}
X
X/******************************************************************************/
X
Xutah_write_pixels(ufp, pixels)
X
XUTAH_FILE	*ufp;
Xunsigned char	pixels[][3];
X{
X	static unsigned	n = 0;
X	static unsigned char	*r = NULL, *g = NULL, *b = NULL;
X	int		i, width;
X
X	/* allocate storage */
X	width = ufp->sv_xmax + 1;
X	if (width > n) {
X		if (n > 0) {
X			free((char *)r);
X			free((char *)g);
X			free((char *)b);
X		}
X		n = width;
X		r = (unsigned char *) malloc(n * sizeof(unsigned char));
X		g = (unsigned char *) malloc(n * sizeof(unsigned char));
X		b = (unsigned char *) malloc(n * sizeof(unsigned char));
X	}
X
X	/* convert to color channels */
X	for (i = 0; i < width; i++) {
X		r[i] = pixels[i][0];
X		g[i] = pixels[i][1];
X		b[i] = pixels[i][2];
X	}
X
X	/* write this row */
X	utah_write_rgb(ufp, r, g, b);
X	return(0);
X}
X
X/******************************************************************************/
X
Xutah_write_rgb(ufp, r, g, b)
X
XUTAH_FILE	*ufp;
Xunsigned char	r[], g[], b[];
X{
X	rle_pixel	*rows[3];
X	int		width;
X
X	/* set color channels */
X	rows[0] = r;
X	rows[1] = g;
X	rows[2] = b;
X
X	/* write this row */
X	width = ufp->sv_xmax - ufp->sv_xmin + 1;
X	sv_putrow(rows, width, ufp);
X	return(0);
X}
X
X/******************************************************************************/
END_OF_FILE
if test 4532 -ne `wc -c <'AALines/utah.c'`; then
    echo shar: \"'AALines/utah.c'\" unpacked with wrong size!
fi
# end of 'AALines/utah.c'
fi
if test -f 'Albers.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Albers.c'\"
else
echo shar: Extracting \"'Albers.c'\" \(3994 characters\)
sed "s/^X//" >'Albers.c' <<'END_OF_FILE'
X/*
XAlbers Equal-Area Conic Map Projection
Xby Paul Bame
Xfrom "Graphics Gems", Academic Press, 1990
X*/
X
X/*
X * Albers Conic Equal-Area Projection
X * Formulae taken from "Map Projections Used by the U.S. 
X * Geological Survey" Bulletin #1532
X *
X * Equation reference numbers and some variable names taken
X * from the reference.
X * To use, call albers setup() once and then albers_project()
X * for each coordinate pair of interest.
X*/
X
X#include "GraphicsGems.h"		
X#include <stdio.h>
X#include <math.h>
X
X/*
X * This is the Clarke 1866 Earth spheroid data which is often
X * used by the USGS - there are other spheroids however - see the
X * book.
X */
X 
X/*
X * Earth radii in different units */
X#define CONST_EradiusKM (6378.2064) 	/* Kilometers */
X#define CONST_EradiusMI (CONST_EradiusKM/1.609)	/* Miles */
X#define CONST_Ec		(0.082271854)	/* Eccentricity */
X#define CONST_Ecsq	(0.006768658)	/* Eccentricity squared */
X
X
X
X/*
X * To keep things simple, assume Earth radius is 1.0. Projected
X * coordinates (X and Y obtained from albers project ()) are
X *  dimensionless and may be multiplied by any desired radius
X *  to convert to desired units (usually Kilometers or Miles).
X*/
X#define CONST_Eradius 1.0
X
X/* Pre-computed variables */
Xstatic double middlelon;		/* longitude at center of map */
Xstatic double bigC, cone_const, r0;	/* See the reference */
X
Xstatic
Xcalc_q_msq(lat, qp, msqp)
Xdouble lat;
Xdouble *qp;
Xdouble *msqp;
X/*
X * Given latitude, calculate 'q' [eq 3-12] 
X * if msqp is != NULL, m^2  [eq. 12-15].
X*/
X{
X	double s, c, es;
X
X	s = sin(lat);
X	es = s * CONST_Ec;
X
X	*qp = (1.0 - CONST_Ecsq) * ((s / (1 - es * es))-
X		(1 / (2 * CONST_Ec)) * log((1 - es) / (1 + es)));
X
X	if (msqp != NULL)
X	{
X		c = cos(lat);
X		*msqp = c * c/ (1 - es * es);
X	}
X}
X
X
X
X
Xalbers_setup(southlat, northlat, originlon, originlat)
Xdouble southlat, northlat;
Xdouble originlon;
Xdouble originlat;
X/*
X * Pre-compute a bunch of variables which are used by the 
X * albers_project()
X *
X * southlat 	Southern latitude for Albers projection
X * northlat	Northern latitute for Albers projection
X * originlon	Longitude for origin of projected map
X * originlat	Latitude for origin of projected map -
X *				often (northlat + southlat) / 2
X*/
X{
X	double q1, q2, q0;
X	double m1sq, m2sq;
X
X	middlelon = originlon;
X	
X	cal_q_msq(southlat, &q1, &m1sq);
X	cal_q_msq(northlat, &q2, &m2sq);
X	cal_q_msq(originlat, &q0, NULL);
X
X	cone_const = (m1sq - m2sq) / (q2 - q1);
X	bigC = m1sq + cone_const * q1;
X	r0 = CONST_Eradius * sqrt(bigC - cone_const *q0) / cone_const;
X}
X
X/***************************************************************/
X
Xalbers_project(lon, lat, xp, yp)
Xdouble lon, lat;
Xdouble *xp, *yp;
X/*
X * Project lon/lat (in radians) according to albers_setup and 
X * return the results via xp, yp. Units of *xp and *yp are same
X * as the units used by CONST_Eradius.
X*/
X{
X	double q, r, theta;
X	calc_q_msq(lat, &q, NULL);
X	theta = cone_const * (lon -middlelon);
X	r = CONST_Eradius * sqrt(bigC - cone_const * q) / cone_const;
X	*xp = r * sin(theta);
X	*yp = r0 - r * cos(theta);
X}
X
X#ifdef TESTPROGRAM
X
X/*
X * Test value from the USGS book. Because of roundoff, the 
X * actual values are printed for visual inspection rather 
X * than guessing what constitutes "close enough".
X*/
X/* Convert a degress, minutes pair to radians */
X#define DEG_MIN2RAD(degrees, minutes) \
X	((double) ((degrees + minutes / 60.0) * M_PI / 180.0))
X
X#define Nlat DEG_MIN2RAD(29, 30)	/* 29 degrees, 30' North Lat */
X#define Slat DEG_MIN2RAD(45, 30)	
X#define Originlat DEG_MIN2RAD(23, 0)	
X#define Originlon DEG_MIN2RAD(-96, 0) /* West longitude is negative */
X
X#define Testlat DEG_MIN2RAD(35, 0)
X#define Testlon DEG_MIN2RAD(-75, 0)
X
X#define TestX 1885.4727
X#define TestY 1535.9250
X
Xmain()
X{
X	int i;
X	double x, y;
X
X/* Setup is also from USGS book test set */
X	albers_setup(Slat, Nlat, Originlon, Originlat);
X
X	albers_project(Testlon, Testlat, &x, &y);
X	printf("%.41f, %.41f =?= %.41f, %.41f/n",
X		x * CONST_EradiusKM, y * CONST_EradiusKM,
X		TestX, TestY);
X}
X#endif		/* TESTPROGRAM */
END_OF_FILE
if test 3994 -ne `wc -c <'Albers.c'`; then
    echo shar: \"'Albers.c'\" unpacked with wrong size!
fi
# end of 'Albers.c'
fi
if test -f 'BoundSphere.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'BoundSphere.c'\"
else
echo shar: Extracting \"'BoundSphere.c'\" \(3767 characters\)
sed "s/^X//" >'BoundSphere.c' <<'END_OF_FILE'
X/*
XAn Efficient Bounding Sphere
Xby Jack Ritter
Xfrom "Graphics Gems", Academic Press, 1990
X*/
X
X/* Routine to calculate tight bounding sphere over    */
X/* a set of points in 3D */
X/* This contains the routine find_bounding_sphere(), */
X/* the struct definition, and the globals used for parameters. */
X/* The abs() of all coordinates must be < BIGNUMBER */
X/* Code written by Jack Ritter and Lyle Rains. */
X
X#include <stdio.h>
X#include <math.h>
X#include "GraphicsGems.h"
X
X#define BIGNUMBER 100000000.0  		/* hundred million */
X
X/* GLOBALS. These are used as input and output parameters. */
X 
Xstruct Point3Struct caller_p,cen;
Xdouble rad;
Xint NUM_POINTS;
X
X/* Call with no parameters. Caller must set NUM_POINTS */
X/* before calling. */
X/* Caller must supply the routine GET_iTH_POINT(i), which loads his */
X/* ith point into the global struct caller_p. (0 <= i < NUM_POINTS). */
X/* The calling order of the points is irrelevant. */
X/* The final bounding sphere will be put into the globals */
X/* cen and rad. */
X
X
Xfind_bounding_sphere()
X{
Xregister int i;
Xregister double dx,dy,dz;
Xregister double rad_sq,xspan,yspan,zspan,maxspan;
Xdouble old_to_p,old_to_p_sq,old_to_new;
Xstruct Point3Struct xmin,xmax,ymin,ymax,zmin,zmax,dia1,dia2;
X
X
X/* FIRST PASS: find 6 minima/maxima points */
Xxmin.x=ymin.y=zmin.z= BIGNUMBER; /* initialize for min/max compare */
Xxmax.x=ymax.y=zmax.z= -BIGNUMBER;
Xfor (i=0;i<NUM_POINTS;i++)
X	{
X	GET_iTH_POINT(i); /* load global struct caller_p with */
X					/* his ith point. */
X	if (caller_p.x<xmin.x)
X		xmin = caller_p; /* New xminimum point */
X	if (caller_p.x>xmax.x)
X		xmax = caller_p;
X	if (caller_p.y<ymin.y)
X		ymin = caller_p;
X	if (caller_p.y>ymax.y)
X		ymax = caller_p;
X	if (caller_p.z<zmin.z)
X		zmin = caller_p;
X	if (caller_p.z>zmax.z)
X		zmax = caller_p;
X	}
X/* Set xspan = distance between the 2 points xmin & xmax (squared) */
Xdx = xmax.x - xmin.x;
Xdy = xmax.y - xmin.y;
Xdz = xmax.z - xmin.z;
Xxspan = dx*dx + dy*dy + dz*dz;
X
X/* Same for y & z spans */
Xdx = ymax.x - ymin.x;
Xdy = ymax.y - ymin.y;
Xdz = ymax.z - ymin.z;
Xyspan = dx*dx + dy*dy + dz*dz;
X
Xdx = zmax.x - zmin.x;
Xdy = zmax.y - zmin.y;
Xdz = zmax.z - zmin.z;
Xzspan = dx*dx + dy*dy + dz*dz;
X
X/* Set points dia1 & dia2 to the maximally seperated pair */
Xdia1 = xmin; dia2 = xmax; /* assume xspan biggest */
Xmaxspan = xspan;
Xif (yspan>maxspan)
X	{
X	maxspan = yspan;
X	dia1 = ymin; dia2 = ymax;
X	}
Xif (zspan>maxspan)
X	{
X	dia1 = zmin; dia2 = zmax;
X	}
X
X
X/* dia1,dia2 is a diameter of initial sphere */
X/* calc initial center */
Xcen.x = (dia1.x+dia2.x)/2.0;
Xcen.y = (dia1.y+dia2.y)/2.0;
Xcen.z = (dia1.z+dia2.z)/2.0;
X/* calculate initial radius**2 and radius */
Xdx = dia2.x-cen.x; /* x componant of radius vector */
Xdy = dia2.y-cen.y; /* y componant of radius vector */
Xdz = dia2.z-cen.z; /* z componant of radius vector */
Xrad_sq = dx*dx + dy*dy + dz*dz;
Xrad = sqrt(rad_sq);
X
X/* SECOND PASS: increment current sphere */
X
Xfor (i=0;i<NUM_POINTS;i++)
X	{
X	GET_iTH_POINT(i); /* load global struct caller_p  */
X					/* with his ith point. */
X	dx = caller_p.x-cen.x;
X	dy = caller_p.y-cen.y;
X	dz = caller_p.z-cen.z;
X	old_to_p_sq = dx*dx + dy*dy + dz*dz;
X	if (old_to_p_sq > rad_sq) 	/* do r**2 test first */
X		{ 	/* this point is outside of current sphere */
X		old_to_p = sqrt(old_to_p_sq);
X		/* calc radius of new sphere */
X		rad = (rad + old_to_p) / 2.0;
X		rad_sq = rad*rad; 	/* for next r**2 compare */
X		old_to_new = old_to_p - rad;
X		/* calc center of new sphere */
X		cen.x = (rad*cen.x + old_to_new*caller_p.x) / old_to_p;
X		cen.y = (rad*cen.y + old_to_new*caller_p.y) / old_to_p;
X		cen.z = (rad*cen.z + old_to_new*caller_p.z) / old_to_p;
X		/* Suppress if desired */
X		printf("\n New sphere: cen,rad = %f %f %f   %f",
X			cen.x,cen.y,cen.z, rad);
X		}	
X	}
X} 			 /* end of find_bounding_sphere()  */
END_OF_FILE
if test 3767 -ne `wc -c <'BoundSphere.c'`; then
    echo shar: \"'BoundSphere.c'\" unpacked with wrong size!
fi
# end of 'BoundSphere.c'
fi
if test -f 'Dissolve.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Dissolve.c'\"
else
echo shar: Extracting \"'Dissolve.c'\" \(4596 characters\)
sed "s/^X//" >'Dissolve.c' <<'END_OF_FILE'
X/* A Digital Dissolve Effect
Xby Mike Morton
Xfrom "Graphics Gems", Academic Press, 1990
X*/
X
X/*
X * Code fragment to advance from one element to the next.
X *
X * int reg;				/* current sequence element
X * reg = 1;				/* start in any non-zero state
X * if (reg & 1)				/* is the bottom bit set?
X * 	reg = (reg >>1) ^ MASK;		/* yes: toss out 1 bit; XOR in mask
X * else reg = reg >>1;			/* no: toss out 0 bit 
X */
X
Xint randmasks[32];	/* Gotta fill this in yourself. */
X
Xdissolve1 (height, width)	/* first version of the dissolve 								/* algorithm */
X	int height, width;	/* number of rows, columns */
X{
X	int pixels, lastnum;	/* number of pixels; */
X				/* last pixel's number */
X	int regwidth;		/* "width" of sequence generator */
X	register long mask;	/* mask to XOR with to*/
X					/* create sequence */
X	register unsigned long element; 
X					/* one element of random sequence */
X	register int row, column;
X					/* row and column numbers for a pixel */
X
X	  /* Find smallest register which produces enough pixel numbers */
X	 pixels = height * width; /* compute number of pixels */
X							/* to dissolve */
X	 lastnum = pixels-1;	/* find last element (they go 0..lastnum) */
X	 regwidth = bitwidth (lastnum); /* how wide must the */
X					/* register be? */
X	 mask = randmasks [regwidth];	/* which mask is for that width? */
X
X	 /* Now cycle through all sequence elements. */
X
X	  element = 1;	/* 1st element (could be any nonzero) */
X
X
X	  do {
X	    row = element / width;	/* how many rows down is this pixel? */
X	    column = element % width;	/* and how many columns across? */
X	    if (row < height)	/* is this seq element in the array? */
X	      copy (row, column);	/* yes: copy the (r,c)'th pixel */
X
X	    /* Compute the next sequence element */
X	    if (element & 1)		/* is the low bit set? */
X	      element = (element >>1)^mask;	/* yes: shift value, */
X						/* XOR in mask */
X	    else element = (element >>1);	/* no: just shift the value */
X	 } while (element != 1);		/* loop until we return  */
X						/* to original element */
X	 copy (0, 0);		/* kludge: the loop doesn't produce (0,0) */
X}						/* end of dissolve1() */
X
X
X
Xint bitwidth (N)	/* find "bit-width" needed to represent N */
X	unsigned int N;	/* number to compute the width of */
X{
X	 int width = 0;	/* initially, no bits needed to represent N */
X	 while (N != 0) {	/* loop 'til N has been whittled down to 0 */
X	    N >>= 1;		/* shift N right 1 bit (NB: N is unsigned) */
X	    width++;		/* and remember how wide N is */
X	  }			/* end of loop shrinking N down to nothing *
X	  return (width);	/* return bit positions counted */
X
X}						/* end of bitwidth() */
X
X
X
Xdissolve2 (height, width)	/* fast version of the dissolve algorithm */
X	int height, width;	/* number of rows, columns */
X{
X	int rwidth, cwidth;	/* bit width for rows, for columns */
X	int regwidth;		/* "width" of sequence generator */
X	register long mask;	/* mask to XOR with to create sequence */
X	register int rowshift;	/* shift distance to get row  */
X							/* from element */
X	register int colmask; /* mask to extract column from element */
X	register unsigned long element; /* one element of random */ 								    /* sequence */
X	register int row, column;    /* row and column for one pixel */
X
X
X	  /* Find the mask to produce all rows and columns. */
X
X	rwidth = bitwidth (height); /* how many bits needed for height? */
X	cwidth = bitwidth (width);  /* how many bits needed for width? */
X	regwidth = rwidth + cwidth; /* how wide must the register be? */
X	mask = randmasks [regwidth]; /* which mask is for that width? */
X
X /* Find values to extract row and col numbers from each element. */
X	rowshift = cwidth; /* find dist to shift to get top bits (row) */
X	colmask = (1<<cwidth)-1;	/* find mask to extract  */
X						/* bottom bits (col) */
X
X	  /* Now cycle through all sequence elements. */
X
X	element = 1;	/* 1st element (could be any nonzero) */
X	do {
X		row = element >> rowshift; /* find row number for this pixel */
X		column = element & colmask; /* and how many columns across? */
X		if ((row < height)	/* does element fall in the array? */
X			&& (column < width)) /* ...must check row AND column */
X		copy (row, column); /* in bounds: copy the (r,c)'th pixel */
X
X	    /* Compute the next sequence element */
X		if (element & 1)		/* is the low bit set? */
X		element = (element >>1)^mask; /* yes: shift value, /*
X						/* XOR in mask */
X		else element = (element >>1); /* no: just shift the value */
X	} while (element != 1); 	/* loop until we return to */
X					/*  original element */
X
X	copy (0, 0);		/* kludge: element never comes up zero */
X}					/* end of dissolve2() */
END_OF_FILE
if test 4596 -ne `wc -c <'Dissolve.c'`; then
    echo shar: \"'Dissolve.c'\" unpacked with wrong size!
fi
# end of 'Dissolve.c'
fi
if test -f 'DoubleLine.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DoubleLine.c'\"
else
echo shar: Extracting \"'DoubleLine.c'\" \(4647 characters\)
sed "s/^X//" >'DoubleLine.c' <<'END_OF_FILE'
X/*
XSymmetric Double Step Line Algorithm
Xby Brian Wyvill
Xfrom "Graphics Gems", Academic Press, 1990
X*/
X
X#define swap(a,b)           {a^=b; b^=a; a^=b;}
X#define absolute(i,j,k)     ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
Xint
Xsymwuline(a1, b1, a2, b2) int a1, b1, a2, b2;
X{
X	int           dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
X	int           x1, y1;
X	int           sign_x, sign_y, step, reverse, i;
X
X	dx = absolute(a2, a1, sign_x);
X	dy = absolute(b2, b1, sign_y);
X	/* decide increment sign by the slope sign */
X	if (sign_x == sign_y)
X		step = 1;
X	else
X		step = -1;
X
X	if (dy > dx) {		/* chooses axis of greatest movement (make
X				 		 * dx) */
X		swap(a1, b1);
X		swap(a2, b2);
X		swap(dx, dy);
X		reverse = 1;
X	} else
X		reverse = 0;
X	/* note error check for dx==0 should be included here */
X	if (a1 > a2) {		/* start from the smaller coordinate */
X		x = a2;
X		y = b2;
X		x1 = a1;
X		y1 = b1;
X	} else {
X		x = a1;
X		y = b1;
X		x1 = a2;
X		y1 = b2;
X	}
X
X
X	/* Note dx=n implies 0 - n or (dx+1) pixels to be set */
X	/* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
X	/* In fact (dx-1)/4 as 2 pixels are already plottted */
X	xend = (dx - 1) / 4;
X	pixels_left = (dx - 1) % 4;	/* number of pixels left over at the
X					 			 * end */
X	plot(x, y, reverse);
X	plot(x1, y1, reverse);	/* plot first two points */
X	incr2 = 4 * dy - 2 * dx;
X	if (incr2 < 0) {	/* slope less than 1/2 */
X		c = 2 * dy;
X		incr1 = 2 * c;
X		D = incr1 - dx;
X
X		for (i = 0; i < xend; i++) {	/* plotting loop */
X			++x;
X			--x1;
X			if (D < 0) {
X                  			/* pattern 1 forwards */
X				plot(x, y, reverse);
X				plot(++x, y, reverse);
X                                /* pattern 1 backwards */
X				plot(x1, y1, reverse);
X				plot(--x1, y1, reverse);
X				D += incr1;
X			} else {
X				if (D < c) {
X					/* pattern 2 forwards */
X					plot(x, y, reverse);
X					plot(++x, y += step, reverse);
X					/* pattern 2 backwards */
X					plot(x1, y1, reverse);
X					plot(--x1, y1 -= step, reverse);	
X				} else {
X				        /* pattern 3 forwards */
X					plot(x, y += step, reverse);
X					plot(++x, y, reverse);
X					/* pattern 3 backwards */
X					plot(x1, y1 -= step, reverse);
X					plot(--x1, y1, reverse);
X				}
X				D + = incr2;
X			}
X		}		/* end for */
X
X		/* plot last pattern */
X		if (pixels_left) {
X			if (D < 0) {
X				plot(++x, y, reverse);	/* pattern 1 */
X				if (pixels_left > 1)
X					plot(++x, y, reverse);
X				if (pixels_left > 2)
X					plot(--x1, y1, reverse);
X			} else {
X				if (D < c) {
X					plot(++x, y, reverse);	/* pattern 2  */
X					if (pixels_left > 1)
X						plot(++x, y += step, reverse);
X					if (pixels_left > 2)
X						plot(--x1, y1, reverse);
X				} else {
X				  /* pattern 3 */
X					plot(++x, y += step, reverse);
X					if (pixels_left > 1)
X						plot(++x, y, reverse);
X					if (pixels_left > 2)
X						plot(--x1, y1 -= step, reverse);
X				}
X			}
X		}		/* end if pixels_left */
X	}
X	/* end slope < 1/2 */
X	else {			/* slope greater than 1/2 */
X		c = 2 * (dy - dx);
X		incr1 = 2 * c;
X		D = incr1 + dx;
X		for (i = 0; i < xend; i++) {
X			++x;
X			--x1;
X			if (D > 0) {
X			  /* pattern 4 forwards */
X				plot(x, y += step, reverse);
X				plot(++x, y += step, reverse);
X			  /* pattern 4 backwards */
X				plot(x1, y1 -= step, reverse);
X				plot(--x1, y1 -= step, reverse);
X				D += incr1;
X			} else {
X				if (D < c) {
X				  /* pattern 2 forwards */
X					plot(x, y, reverse);
X					plot(++x, y += step, reverse);
X
X 				  /* pattern 2 backwards */
X					plot(x1, y1, reverse);
X					plot(--x1, y1 -= step, reverse);
X				} else {
X				  /* pattern 3 forwards */
X					plot(x, y += step, reverse);
X					plot(++x, y, reverse);
X				  /* pattern 3 backwards */
X					plot(x1, y1 -= step, reverse);
X					plot(--x1, y1, reverse);
X				}
X				D += incr2;
X			}
X		}		/* end for */
X		/* plot last pattern */
X		if (pixels_left) {
X			if (D > 0) {
X				plot(++x, y += step, reverse);	/* pattern 4 */
X				if (pixels_left > 1)
X					plot(++x, y += step, reverse);
X				if (pixels_left > 2)
X					plot(--x1, y1 -= step, reverse);
X			} else {
X				if (D < c) {
X					plot(++x, y, reverse);	/* pattern 2  */
X					if (pixels_left > 1)
X						plot(++x, y += step, reverse);
X					if (pixels_left > 2)
X						plot(--x1, y1, reverse);
X				} else {
X				  /* pattern 3 */
X					plot(++x, y += step, reverse);
X					if (pixels_left > 1)
X						plot(++x, y, reverse);
X					if (pixels_left > 2) {
X						if (D > c) /* step 3 */
X						   plot(--x1, y1 -= step, reverse);
X						else /* step 2 */
X							plot(--x1, y1, reverse);
X                         		}
X				}
X			}
X		}
X	}
X}
X/* non-zero flag indicates the pixels needing swap back. */
Xplot(x, y, flag) int x, y, flag;
X{
X	if (flag)
X		setpixel(y, x);
X	else
X		setpixel(x, y);
X}
X
END_OF_FILE
if test 4647 -ne `wc -c <'DoubleLine.c'`; then
    echo shar: \"'DoubleLine.c'\" unpacked with wrong size!
fi
# end of 'DoubleLine.c'
fi
if test -f 'GraphicsGems.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'GraphicsGems.h'\"
else
echo shar: Extracting \"'GraphicsGems.h'\" \(4049 characters\)
sed "s/^X//" >'GraphicsGems.h' <<'END_OF_FILE'
X/* 
X * GraphicsGems.h  
X * Version 1.0 - Andrew Glassner
X * from "Graphics Gems", Academic Press, 1990
X */
X
X#ifndef GG_H
X
X#define GG_H 1
X
X/*********************/
X/* 2d geometry types */
X/*********************/
X
Xtypedef struct Point2Struct {	/* 2d point */
X	double x, y;
X	} Point2;
Xtypedef Point2 Vector2;
X
Xtypedef struct IntPoint2Struct {	/* 2d integer point */
X	int x, y;
X	} IntPoint2;
X
Xtypedef struct Matrix3Struct {	/* 3-by-3 matrix */
X	double element[3][3];
X	} Matrix3;
X
Xtypedef struct Box2dStruct {		/* 2d box */
X	Point2 min, max;
X	} Box2;
X	
X
X/*********************/
X/* 3d geometry types */
X/*********************/
X
Xtypedef struct Point3Struct {	/* 3d point */
X	double x, y, z;
X	} Point3;
Xtypedef Point3 Vector3;
X
Xtypedef struct IntPoint3Struct {	/* 3d integer point */
X	int x, y, z;
X	} IntPoint3;
X
X
Xtypedef struct Matrix4Struct {	/* 4-by-4 matrix */
X	double element[4][4];
X	} Matrix4;
X
Xtypedef struct Box3dStruct {		/* 3d box */
X	Point3 min, max;
X	} Box3;
X
X
X
X/***********************/
X/* one-argument macros */
X/***********************/
X
X/* absolute value of a */
X#define ABS(a)		(((a)<0) ? -(a) : (a))
X
X/* round a to nearest integer towards 0 */
X#define FLOOR(a)		((a)>0 ? (int)(a) : -(int)(-a))
X
X/* round a to nearest integer away from 0 */
X#define CEILING(a) \
X((a)==(int)(a) ? (a) : (a)>0 ? 1+(int)(a) : -(1+(int)(-a)))
X
X/* round a to nearest int */
X#define ROUND(a)	((a)>0 ? (int)(a+0.5) : -(int)(0.5-a))		
X
X/* take sign of a, either -1, 0, or 1 */
X#define ZSGN(a)		(((a)<0) ? -1 : (a)>0 ? 1 : 0)	
X
X/* take binary sign of a, either -1, or 1 if >= 0 */
X#define SGN(a)		(((a)<0) ? -1 : 0)
X
X/* shout if something that should be true isn't */
X#define ASSERT(x) \
Xif (!(x)) fprintf(stderr," Assert failed: x\n");
X
X/* square a */
X#define SQR(a)		((a)*(a))	
X
X
X/***********************/
X/* two-argument macros */
X/***********************/
X
X/* find minimum of a and b */
X#define MIN(a,b)	(((a)<(b))?(a):(b))	
X
X/* find maximum of a and b */
X#define MAX(a,b)	(((a)>(b))?(a):(b))	
X
X/* swap a and b (see Gem by Wyvill) */
X#define SWAP(a,b)	{ a^=b; b^=a; a^=b; }
X
X/* linear interpolation from l (when a=0) to h (when a=1)*/
X/* (equal to (a*h)+((1-a)*l) */
X#define LERP(a,l,h)	((l)+(((h)-(l))*(a)))
X
X/* clamp the input to the specified range */
X#define CLAMP(v,l,h)	((v)<(l) ? (l) : (v) > (h) ? (h) : v)
X
X
X/****************************/
X/* memory allocation macros */
X/****************************/
X
X/* create a new instance of a structure (see Gem by Hultquist) */
X#define NEWSTRUCT(x)	(struct x *)(malloc((unsigned)sizeof(struct x)))
X
X/* create a new instance of a type */
X#define NEWTYPE(x)	(x *)(malloc((unsigned)sizeof(x)))
X
X
X/********************/
X/* useful constants */
X/********************/
X
X#define PI		3.141592	/* the venerable pi */
X#define PITIMES2	6.283185	/* 2 * pi */
X#define PIOVER2		1.570796	/* pi / 2 */
X#define E		2.718282	/* the venerable e */
X#define SQRT2		1.414214	/* sqrt(2) */
X#define SQRT3		1.732051	/* sqrt(3) */
X#define GOLDEN		1.618034	/* the golden ratio */
X#define DTOR		0.017453	/* convert degrees to radians */
X#define RTOD		57.29578	/* convert radians to degrees */
X
X
X/************/
X/* booleans */
X/************/
X
X#define TRUE		1
X#define FALSE		0
X#define ON		1
X#define OFF 		0
Xtypedef int boolean;			/* boolean data type */
Xtypedef boolean flag;			/* flag data type */
X
Xextern double V2SquaredLength(), V2Length();
Xextern double V2Dot(), V2DistanceBetween2Points(); 
Xextern Vector2 *V2Negate(), *V2Normalize(), *V2Scale(), *V2Add(), *V2Sub();
Xextern Vector2 *V2Lerp(), *V2Combine(), *V2Mul(), *V2MakePerpendicular();
Xextern Vector2 *V2New(), *V2Duplicate();
Xextern Point2 *V2MulPointByMatrix();
Xextern Matrix3 *V2MatMul();
X
Xextern double V3SquaredLength(), V3Length();
Xextern double V3Dot(), V3DistanceBetween2Points();
Xextern Vector3 *V3Normalize(), *V3Scale(), *V3Add(), *V3Sub();
Xextern Vector3 *V3Lerp(), *V3Combine(), *V3Mul(), *V3Cross();
Xextern Vector3 *V3New(), *V3Duplicate();
Xextern Point3 *V3MulPointByMatrix();
Xextern Matrix4 *V3MatMul();
X
Xextern double RegulaFalsi(), NewtonRaphson(), findroot();
X
X#endif
END_OF_FILE
if test 4049 -ne `wc -c <'GraphicsGems.h'`; then
    echo shar: \"'GraphicsGems.h'\" unpacked with wrong size!
fi
# end of 'GraphicsGems.h'
fi
if test -f 'LineEdge.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'LineEdge.c'\"
else
echo shar: Extracting \"'LineEdge.c'\" \(3852 characters\)
sed "s/^X//" >'LineEdge.c' <<'END_OF_FILE'
X/* 
XFast Line-Edge Intersections on a Uniform Grid 
Xby Andrew Shapira
Xfrom "Graphics Gems", Academic Press, 1990
X*/
X
X#include "GraphicsGems.h"
X
X#define OCTANT(f1, f2, f3, f4, f5, i1, s1, r1, r2) \
X    for (f1, f2, f3, nr = 0; f4; f5) { \
X        if (nr < liconst) { \
X            if (i1) \
X                r1(&C); \
X            else \
X                vertex(&C); \
X        } \
X        else { \
X            s1; \
X            if (nr -= liconst) { \
X                r2(&C); \
X                r1(&C); \
X            } \
X            else \
X                vertex(&C); \
X        } \
X    }
X
Xfind_intersections(Pptr, Qptr)
XIntPoint2   *Pptr, *Qptr;       /* P and Q as described in gem text */
X{
X    IntPoint2   P, Q;           /* P and Q, dereferenced for speed */
X    IntPoint2   C;              /* current grid point */
X    int         nr;             /* remainder */
X    int         deltax, deltay; /* Q.x - P.x, Q.y - P.y */
X    int         liconst;          /* loop-invariant constant */
X
X    P.x = Pptr->x;
X    P.y = Pptr->y;
X    Q.x = Qptr->x;
X    Q.y = Qptr->y;
X    deltax = Q.x - P.x;
X    deltay = Q.y - P.y;
X
X
X    /* for reference purposes, let theta be the angle from P to Q */
X
X    if ((deltax >= 0) && (deltay >= 0) && (deltay < deltax)) 
X						/* 0 <= theta < 45 */
X        OCTANT(C.x = P.x + 1, C.y = P.y, liconst = deltax - deltay, 
X			C.x < Q.x, C.x++, nr += deltay, C.y++, up, left)
X    else if ((deltax > 0) && (deltay >= 0) && (deltay >= deltax)) 
X					   /* 45 <= theta < 90 */
X        OCTANT(C.y = P.y + 1, C.x = P.x, liconst = deltay - deltax,
X			 C.y < Q.y, C.y++, nr += deltax, C.x++, right, down)
X    else if ((deltax <= 0) && (deltay >= 0) && (deltay > -deltax))
X					   /* 90 <= theta < 135 */
X        OCTANT(C.y = P.y + 1, C.x = P.x, liconst = deltay + deltax,
X			 C.y < Q.y, C.y++, nr -= deltax, C.x--, left, down)
X    else if ((deltax <= 0) && (deltay > 0) && (deltay <= -deltax)) 
X					   /* 135 <= theta < 180 */
X        OCTANT(C.x = P.x - 1, C.y = P.y, liconst = -deltax - deltay,
X			 C.x > Q.x, C.x--, nr += deltay, C.y++, up, right)
X    else if ((deltax <= 0) && (deltay <= 0) && (deltay > deltax))
X				      /* 180 <= theta < 225 */
X        OCTANT(C.x = P.x - 1, C.y = P.y, liconst = -deltax + deltay, 
X			C.x > Q.x, C.x--, nr -= deltay, C.y--, down, right)
X    else if ((deltax < 0) && (deltay <= 0) && (deltay <= deltax))
X				      /* 225 <= theta < 270 */
X        OCTANT(C.y = P.y - 1, C.x = P.x, liconst = -deltay + deltax,
X			C.y > Q.y, C.y--, nr -= deltax, C.x--, left, up)
X    else if ((deltax >= 0) && (deltay <= 0) && (-deltay > deltax))
X				     /* 270 <= theta < 315 */
X        OCTANT(C.y = P.y - 1, C.x = P.x, liconst = -deltay - deltax, 
X			C.y > Q.y, C.y--, nr += deltax, C.x++, right, up)
X    else if ((deltax >= 0) && (deltay < 0) && (-deltay <= deltax))
X				     /* 315 <= theta < 360 */
X        OCTANT(C.x = P.x + 1, C.y = P.y, liconst = deltax + deltay,
X			 C.x < Q.x, C.x++, nr -= deltay, C.y--, down, left)
X    else {}                    /* P = Q */
X}
X
Xvertex(I)
XIntPoint2   *I;
X{
X    /* Note: replace printf with code to process vertex, if desired */
X    (void) printf("vertex at %d %d\n", I->x, I->y);
X}
X
Xleft(I)
XIntPoint2   *I;
X{
X
X    /* Note: replace printf with code to process leftward */ 	
X	/* intersection, if desired */
X    (void) printf("left from %d %d\n", I->x, I->y);
X}
X
Xup(I)
XIntPoint2   *I;
X{
X    /* Note: replace printf with code to process upward */
X	/* intersection, if desired */
X    (void) printf("up from %d %d\n", I->x, I->y);
X}
X
Xright(I)
XIntPoint2   *I;
X{
X    /* Note: replace printf with code to process rightward */
X	/* intersection, if desired */
X    (void) printf("right from %d %d\n", I->x, I->y);
X}
X
Xdown(I)
XIntPoint2   *I;
X{
X    /* Note: replace printf with code to process downward */
X	/* intersection, if desired */
X    (void) printf("down from %d %d\n", I->x, I->y);
X}
END_OF_FILE
if test 3852 -ne `wc -c <'LineEdge.c'`; then
    echo shar: \"'LineEdge.c'\" unpacked with wrong size!
fi
# end of 'LineEdge.c'
fi
if test -f 'MatrixInvert.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MatrixInvert.c'\"
else
echo shar: Extracting \"'MatrixInvert.c'\" \(4893 characters\)
sed "s/^X//" >'MatrixInvert.c' <<'END_OF_FILE'
X/*
XMatrix Inversion
Xby Richard Carling
Xfrom "Graphics Gems", Academic Press, 1990
X*/
X
X#define SMALL_NUMBER	1.e-8
X/* 
X *   inverse( original_matrix, inverse_matrix )
X * 
X *    calculate the inverse of a 4x4 matrix
X *
X *     -1     
X *     A  = ___1__ adjoint A
X *         det A
X */
X
X#include "GraphicsGems.h"
Xinverse( in, out ) Matrix4 *in, *out;
X{
X    int i, j;
X    double det, det4x4();
X
X    /* calculate the adjoint matrix */
X
X    adjoint( in, out );
X
X    /*  calculate the 4x4 determinent
X     *  if the determinent is zero, 
X     *  then the inverse matrix is not unique.
X     */
X
X    det = det4x4( in );
X
X    if ( fabs( det ) < SMALL_NUMBER) {
X        printf("Non-singular matrix, no inverse!\n");
X        exit();
X    }
X
X    /* scale the adjoint matrix to get the inverse */
X
X    for (i=0; i<4; i++)
X        for(j=0; j<4; j++)
X	    out->element[i][j] = out->element[i][j] / det;
X}
X
X
X/* 
X *   adjoint( original_matrix, inverse_matrix )
X * 
X *     calculate the adjoint of a 4x4 matrix
X *
X *      Let  a   denote the minor determinant of matrix A obtained by
X *           ij
X *
X *      deleting the ith row and jth column from A.
X *
X *                    i+j
X *     Let  b   = (-1)    a
X *          ij            ji
X *
X *    The matrix B = (b  ) is the adjoint of A
X *                     ij
X */
X
Xadjoint( in, out ) Matrix4 *in; Matrix4 *out;
X{
X    double a1, a2, a3, a4, b1, b2, b3, b4;
X    double c1, c2, c3, c4, d1, d2, d3, d4;
X    double det3x3();
X
X    /* assign to individual variable names to aid  */
X    /* selecting correct values  */
X
X	a1 = in->element[0][0]; b1 = in->element[0][1]; 
X	c1 = in->element[0][2]; d1 = in->element[0][3];
X
X	a2 = in->element[1][0]; b2 = in->element[1][1]; 
X	c2 = in->element[1][2]; d2 = in->element[1][3];
X
X	a3 = in->element[2][0]; b3 = in->element[2][1];
X	c3 = in->element[2][2]; d3 = in->element[2][3];
X
X	a4 = in->element[3][0]; b4 = in->element[3][1]; 
X	c4 = in->element[3][2]; d4 = in->element[3][3];
X
X
X    /* row column labeling reversed since we transpose rows & columns */
X
X    out->element[0][0]  =   det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
X    out->element[1][0]  = - det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
X    out->element[2][0]  =   det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
X    out->element[3][0]  = - det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
X        
X    out->element[0][1]  = - det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
X    out->element[1][1]  =   det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
X    out->element[2][1]  = - det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
X    out->element[3][1]  =   det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
X        
X    out->element[0][2]  =   det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
X    out->element[1][2]  = - det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
X    out->element[2][2]  =   det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
X    out->element[3][2]  = - det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
X        
X    out->element[0][3]  = - det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
X    out->element[1][3]  =   det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
X    out->element[2][3]  = - det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
X    out->element[3][3]  =   det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
X}
X/*
X * double = det4x4( matrix )
X * 
X * calculate the determinent of a 4x4 matrix.
X */
Xdouble det4x4( m ) Matrix4 *m;
X{
X    double ans;
X    double a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, 			d4;
X    double det3x3();
X
X    /* assign to individual variable names to aid selecting */
X	/*  correct elements */
X
X	a1 = m->element[0][0]; b1 = m->element[0][1]; 
X	c1 = m->element[0][2]; d1 = m->element[0][3];
X
X	a2 = m->element[1][0]; b2 = m->element[1][1]; 
X	c2 = m->element[1][2]; d2 = m->element[1][3];
X
X	a3 = m->element[2][0]; b3 = m->element[2][1]; 
X	c3 = m->element[2][2]; d3 = m->element[2][3];
X
X	a4 = m->element[3][0]; b4 = m->element[3][1]; 
X	c4 = m->element[3][2]; d4 = m->element[3][3];
X
X    ans = a1 * det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
X        - b1 * det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
X        + c1 * det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
X        - d1 * det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
X    return ans;
X}
X
X
X
X/*
X * double = det3x3(  a1, a2, a3, b1, b2, b3, c1, c2, c3 )
X * 
X * calculate the determinent of a 3x3 matrix
X * in the form
X *
X *     | a1,  b1,  c1 |
X *     | a2,  b2,  c2 |
X *     | a3,  b3,  c3 |
X */
X
Xdouble det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 )
Xdouble a1, a2, a3, b1, b2, b3, c1, c2, c3;
X{
X    double ans;
X    double det2x2();
X
X    ans = a1 * det2x2( b2, b3, c2, c3 )
X        - b1 * det2x2( a2, a3, c2, c3 )
X        + c1 * det2x2( a2, a3, b2, b3 );
X    return ans;
X}
X
X/*
X * double = det2x2( double a, double b, double c, double d )
X * 
X * calculate the determinent of a 2x2 matrix.
X */
X
Xdouble det2x2( a, b, c, d)
Xdouble a, b, c, d; 
X{
X    double ans;
X    ans = a * d - b * c;
X    return ans;
X}
X
X
END_OF_FILE
if test 4893 -ne `wc -c <'MatrixInvert.c'`; then
    echo shar: \"'MatrixInvert.c'\" unpacked with wrong size!
fi
# end of 'MatrixInvert.c'
fi
if test -f 'PolyScan/poly_clip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'PolyScan/poly_clip.c'\"
else
echo shar: Extracting \"'PolyScan/poly_clip.c'\" \(4217 characters\)
sed "s/^X//" >'PolyScan/poly_clip.c' <<'END_OF_FILE'
X/*
X * Generic Convex Polygon Scan Conversion and Clipping
X * by Paul Heckbert
X * from "Graphics Gems", Academic Press, 1990
X */
X
X/*
X * poly_clip.c: homogeneous 3-D convex polygon clipper
X *
X * Paul Heckbert	1985, Dec 1989
X */
X
X#include "poly.h"
X
X#define SWAP(a, b, temp)	{temp = a; a = b; b = temp;}
X#define COORD(vert, i) ((double *)(vert))[i]
X
X#define CLIP_AND_SWAP(elem, sign, k, p, q, r) { \
X    poly_clip_to_halfspace(p, q, &v->elem-(double *)v, sign, sign*k); \
X    if (q->n==0) {p1->n = 0; return POLY_CLIP_OUT;} \
X    SWAP(p, q, r); \
X}
X
X/*
X * poly_clip_to_box: Clip the convex polygon p1 to the screen space box
X * using the homogeneous screen coordinates (sx, sy, sz, sw) of each vertex,
X * testing if v->sx/v->sw > box->x0 and v->sx/v->sw < box->x1,
X * and similar tests for y and z, for each vertex v of the polygon.
X * If polygon is entirely inside box, then POLY_CLIP_IN is returned.
X * If polygon is entirely outside box, then POLY_CLIP_OUT is returned.
X * Otherwise, if the polygon is cut by the box, p1 is modified and
X * POLY_CLIP_PARTIAL is returned.
X */
X
Xint poly_clip_to_box(p1, box)
Xregister Poly *p1;
Xregister Poly_box *box;
X{
X    int x0out = 0, x1out = 0, y0out = 0, y1out = 0, z0out = 0, z1out = 0;
X    register int i;
X    register Poly_vert *v;
X    Poly p2, *p, *q, *r;
X
X    /* count vertices "outside" with respect to each of the six planes */
X    for (v=p1->vert, i=p1->n; i>0; i--, v++) {
X	if (v->sx < box->x0*v->sw) x0out++;	/* out on left */
X	if (v->sx > box->x1*v->sw) x1out++;	/* out on right */
X	if (v->sy < box->y0*v->sw) y0out++;	/* out on top */
X	if (v->sy > box->y1*v->sw) y1out++;	/* out on bottom */
X	if (v->sz < box->z0*v->sw) z0out++;	/* out on near */
X	if (v->sz > box->z1*v->sw) z1out++;	/* out on far */
X    }
X
X    /* check if all vertices inside */
X    if (x0out+x1out+y0out+y1out+z0out+z1out == 0) return POLY_CLIP_IN;
X
X    /* check if all vertices are "outside" any of the six planes */
X    if (x0out==p1->n || x1out==p1->n || y0out==p1->n ||
X	y1out==p1->n || z0out==p1->n || z1out==p1->n) {
X	    p1->n = 0;
X	    return POLY_CLIP_OUT;
X	}
X
X    /*
X     * now clip against each of the planes that might cut the polygon,
X     * at each step toggling between polygons p1 and p2
X     */
X    p = p1;
X    q = &p2;
X    if (x0out) CLIP_AND_SWAP(sx, -1., box->x0, p, q, r);
X    if (x1out) CLIP_AND_SWAP(sx,  1., box->x1, p, q, r);
X    if (y0out) CLIP_AND_SWAP(sy, -1., box->y0, p, q, r);
X    if (y1out) CLIP_AND_SWAP(sy,  1., box->y1, p, q, r);
X    if (z0out) CLIP_AND_SWAP(sz, -1., box->z0, p, q, r);
X    if (z1out) CLIP_AND_SWAP(sz,  1., box->z1, p, q, r);
X
X    /* if result ended up in p2 then copy it to p1 */
X    if (p==&p2)
X	bcopy(&p2, p1, sizeof(Poly)-(POLY_NMAX-p2.n)*sizeof(Poly_vert));
X    return POLY_CLIP_PARTIAL;
X}
X
X/*
X * poly_clip_to_halfspace: clip convex polygon p against a plane,
X * copying the portion satisfying sign*s[index] < k*sw into q,
X * where s is a Poly_vert* cast as a double*.
X * index is an index into the array of doubles at each vertex, such that
X * s[index] is sx, sy, or sz (screen space x, y, or z).
X * Thus, to clip against xmin, use
X *	poly_clip_to_halfspace(p, q, XINDEX, -1., -xmin);
X * and to clip against xmax, use
X *	poly_clip_to_halfspace(p, q, XINDEX,  1.,  xmax);
X */
X
Xvoid poly_clip_to_halfspace(p, q, index, sign, k)
XPoly *p, *q;
Xregister int index;
Xdouble sign, k;
X{
X    register int m;
X    register double *up, *vp, *wp;
X    register Poly_vert *v;
X    int i;
X    Poly_vert *u;
X    double t, tu, tv;
X
X    q->n = 0;
X    q->mask = p->mask;
X
X    /* start with u=vert[n-1], v=vert[0] */
X    u = &p->vert[p->n-1];
X    tu = sign*COORD(u, index) - u->sw*k;
X    for (v= &p->vert[0], i=p->n; i>0; i--, u=v, tu=tv, v++) {
X	/* on old polygon (p), u is previous vertex, v is current vertex */
X	/* tv is negative if vertex v is in */
X	tv = sign*COORD(v, index) - v->sw*k;
X	if (tu<=0. ^ tv<=0.) {
X	    /* edge crosses plane; add intersection point to q */
X	    t = tu/(tu-tv);
X	    up = (double *)u;
X	    vp = (double *)v;
X	    wp = (double *)&q->vert[q->n];
X	    for (m=p->mask; m!=0; m>>=1, up++, vp++, wp++)
X		if (m&1) *wp = *up+t*(*vp-*up);
X	    q->n++;
X	}
X	if (tv<=0.)		/* vertex v is in, copy it to q */
X	    q->vert[q->n++] = *v;
X    }
X}
END_OF_FILE
if test 4217 -ne `wc -c <'PolyScan/poly_clip.c'`; then
    echo shar: \"'PolyScan/poly_clip.c'\" unpacked with wrong size!
fi
# end of 'PolyScan/poly_clip.c'
fi
if test -f 'PolyScan/poly_scan.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'PolyScan/poly_scan.c'\"
else
echo shar: Extracting \"'PolyScan/poly_scan.c'\" \(4638 characters\)
sed "s/^X//" >'PolyScan/poly_scan.c' <<'END_OF_FILE'
X/*
X * Generic Convex Polygon Scan Conversion and Clipping
X * by Paul Heckbert
X * from "Graphics Gems", Academic Press, 1990
X */
X
X/*
X * poly_scan.c: point-sampled scan conversion of convex polygons
X *
X * Paul Heckbert	1985, Dec 1989
X */
X
X#include <stdio.h>
X#include <math.h>
X#include "poly.h"
X
X/*
X * poly_scan: Scan convert a polygon, calling pixelproc at each pixel with an
X * interpolated Poly_vert structure.  Polygon can be clockwise or ccw.
X * Polygon is clipped in 2-D to win, the screen space window.
X *
X * Scan conversion is done on the basis of Poly_vert fields sx and sy.
X * These two must always be interpolated, and only they have special meaning
X * to this code; any other fields are blindly interpolated regardless of
X * their semantics.
X *
X * The pixelproc subroutine takes the arguments:
X *
X *	pixelproc(x, y, point)
X *	int x, y;
X *	Poly_vert *point;
X *
X * All the fields of point indicated by p->mask will be valid inside pixelproc
X * except sx and sy.  If they were computed, they would have values
X * sx=x+.5 and sy=y+.5, since sampling is done at pixel centers.
X */
X
Xvoid poly_scan(p, win, pixelproc)
Xregister Poly *p;		/* polygon */
XWindow *win;			/* 2-D screen space clipping window */
Xvoid (*pixelproc)();		/* procedure called at each pixel */
X{
X    register int i, li, ri, y, ly, ry, top, rem, mask;
X    double ymin;
X    Poly_vert l, r, dl, dr;
X
X    if (p->n>POLY_NMAX) {
X	fprintf(stderr, "poly_scan: too many vertices: %d\n", p->n);
X	return;
X    }
X
X    ymin = HUGE;
X    for (i=0; i<p->n; i++)		/* find top vertex (y points down) */
X	if (p->vert[i].sy < ymin) {
X	    ymin = p->vert[i].sy;
X	    top = i;
X	}
X
X    li = ri = top;			/* left and right vertex indices */
X    rem = p->n;				/* number of vertices remaining */
X    y = ceil(ymin-.5);			/* current scan line */
X    ly = ry = y-1;			/* lower end of left & right edges */
X    mask = p->mask & ~POLY_MASK(sy);	/* stop interpolating screen y */
X
X    while (rem>0) {	/* scan in y, activating new edges on left & right */
X			/* as scan line passes over new vertices */
X
X	while (ly<=y && rem>0) {	/* advance left edge? */
X	    rem--;
X	    i = li-1;			/* step ccw down left side */
X	    if (i<0) i = p->n-1;
X	    incrementalize_y(&p->vert[li], &p->vert[i], &l, &dl, y, mask);
X	    ly = floor(p->vert[i].sy+.5);
X	    li = i;
X	}
X	while (ry<=y && rem>0) {	/* advance right edge? */
X	    rem--;
X	    i = ri+1;			/* step cw down right edge */
X	    if (i>=p->n) i = 0;
X	    incrementalize_y(&p->vert[ri], &p->vert[i], &r, &dr, y, mask);
X	    ry = floor(p->vert[i].sy+.5);
X	    ri = i;
X	}
X
X	while (y<ly && y<ry) {	    /* do scanlines till end of l or r edge */
X	    if (y>=win->y0 && y<=win->y1)
X		if (l.sx<=r.sx) scanline(y, &l, &r, win, pixelproc, mask);
X		else		scanline(y, &r, &l, win, pixelproc, mask);
X	    y++;
X	    increment(&l, &dl, mask);
X	    increment(&r, &dr, mask);
X	}
X    }
X}
X
X/* scanline: output scanline by sampling polygon at Y=y+.5 */
X
Xstatic scanline(y, l, r, win, pixelproc, mask)
Xint y, mask;
XPoly_vert *l, *r;
XWindow *win;
Xvoid (*pixelproc)();
X{
X    int x, lx, rx;
X    Poly_vert p, dp;
X
X    mask &= ~POLY_MASK(sx);		/* stop interpolating screen x */
X    lx = ceil(l->sx-.5);
X    if (lx<win->x0) lx = win->x0;
X    rx = floor(r->sx-.5);
X    if (rx>win->x1) rx = win->x1;
X    if (lx>rx) return;
X    incrementalize_x(l, r, &p, &dp, lx, mask);
X    for (x=lx; x<=rx; x++) {		/* scan in x, generating pixels */
X	(*pixelproc)(x, y, &p);
X	increment(&p, &dp, mask);
X    }
X}
X
X/*
X * incrementalize_y: put intersection of line Y=y+.5 with edge between points
X * p1 and p2 in p, put change with respect to y in dp
X */
X
Xstatic incrementalize_y(p1, p2, p, dp, y, mask)
Xregister double *p1, *p2, *p, *dp;
Xregister int mask;
Xint y;
X{
X    double dy, frac;
X
X    dy = ((Poly_vert *)p2)->sy - ((Poly_vert *)p1)->sy;
X    if (dy==0.) dy = 1.;
X    frac = y+.5 - ((Poly_vert *)p1)->sy;
X
X    for (; mask!=0; mask>>=1, p1++, p2++, p++, dp++)
X	if (mask&1) {
X	    *dp = (*p2-*p1)/dy;
X	    *p = *p1+*dp*frac;
X	}
X}
X
X/*
X * incrementalize_x: put intersection of line X=x+.5 with edge between points
X * p1 and p2 in p, put change with respect to x in dp
X */
X
Xstatic incrementalize_x(p1, p2, p, dp, x, mask)
Xregister double *p1, *p2, *p, *dp;
Xregister int mask;
Xint x;
X{
X    double dx, frac;
X
X    dx = ((Poly_vert *)p2)->sx - ((Poly_vert *)p1)->sx;
X    if (dx==0.) dx = 1.;
X    frac = x+.5 - ((Poly_vert *)p1)->sx;
X
X    for (; mask!=0; mask>>=1, p1++, p2++, p++, dp++)
X	if (mask&1) {
X	    *dp = (*p2-*p1)/dx;
X	    *p = *p1+*dp*frac;
X	}
X}
X
Xstatic increment(p, dp, mask)
Xregister double *p, *dp;
Xregister int mask;
X{
X    for (; mask!=0; mask>>=1, p++, dp++)
X	if (mask&1)
X	    *p += *dp;
X}
END_OF_FILE
if test 4638 -ne `wc -c <'PolyScan/poly_scan.c'`; then
    echo shar: \"'PolyScan/poly_scan.c'\" unpacked with wrong size!
fi
# end of 'PolyScan/poly_scan.c'
fi
if test -f 'Roots3And4.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Roots3And4.c'\"
else
echo shar: Extracting \"'Roots3And4.c'\" \(4127 characters\)
sed "s/^X//" >'Roots3And4.c' <<'END_OF_FILE'
X/*
X *  Roots3And4.c
X *
X *  Utility functions to find cubic and quartic roots,
X *  coefficients are passed like this:
X *
X *      c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0
X *
X *  The functions return the number of non-complex roots and
X *  put the values into the s array.
X *
X *  Author:         Jochen Schwarze (schwarze@isa.de)
X *
X *  Jan 26, 1990    Version for Graphics Gems
X *  Oct 11, 1990    Fixed sign problem for negative q's in SolveQuartic
X *  	    	    (reported by Mark Podlipec),
X *  	    	    Old-style function definitions,
X *  	    	    IsZero() as a macro
X */
X
X#include    <math.h>
X
X/* epsilon surrounding for near zero values */
X
X#define     EQN_EPS     1e-9
X#define	    IsZero(x)	((x) > -EQN_EPS && (x) < EQN_EPS)
X
X
Xint SolveQuadric(c, s)
X    double c[ 3 ];
X    double s[ 2 ];
X{
X    double p, q, D;
X
X    /* normal form: x^2 + px + q = 0 */
X
X    p = c[ 1 ] / (2 * c[ 2 ]);
X    q = c[ 0 ] / c[ 2 ];
X
X    D = p * p - q;
X
X    if (IsZero(D))
X    {
X	s[ 0 ] = - p;
X	return 1;
X    }
X    else if (D < 0)
X    {
X	return 0;
X    }
X    else if (D > 0)
X    {
X	double sqrt_D = sqrt(D);
X
X	s[ 0 ] =   sqrt_D - p;
X	s[ 1 ] = - sqrt_D - p;
X	return 2;
X    }
X}
X
X
Xint SolveCubic(c, s)
X    double c[ 4 ];
X    double s[ 3 ];
X{
X    int     i, num;
X    double  sub;
X    double  A, B, C;
X    double  sq_A, p, q;
X    double  cb_p, D;
X
X    /* normal form: x^3 + Ax^2 + Bx + C = 0 */
X
X    A = c[ 2 ] / c[ 3 ];
X    B = c[ 1 ] / c[ 3 ];
X    C = c[ 0 ] / c[ 3 ];
X
X    /*  substitute x = y - A/3 to eliminate quadric term:
X	x^3 +px + q = 0 */
X
X    sq_A = A * A;
X    p = 1.0/3 * (- 1.0/3 * sq_A + B);
X    q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);
X
X    /* use Cardano's formula */
X
X    cb_p = p * p * p;
X    D = q * q + cb_p;
X
X    if (IsZero(D))
X    {
X	if (IsZero(q)) /* one triple solution */
X	{
X	    s[ 0 ] = 0;
X	    num = 1;
X	}
X	else /* one single and one double solution */
X	{
X	    double u = cbrt(-q);
X	    s[ 0 ] = 2 * u;
X	    s[ 1 ] = - u;
X	    num = 2;
X	}
X    }
X    else if (D < 0) /* Casus irreducibilis: three real solutions */
X    {
X	double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
X	double t = 2 * sqrt(-p);
X
X	s[ 0 ] =   t * cos(phi);
X	s[ 1 ] = - t * cos(phi + M_PI / 3);
X	s[ 2 ] = - t * cos(phi - M_PI / 3);
X	num = 3;
X    }
X    else /* one real solution */
X    {
X	double sqrt_D = sqrt(D);
X	double u = cbrt(sqrt_D - q);
X	double v = - cbrt(sqrt_D + q);
X
X	s[ 0 ] = u + v;
X	num = 1;
X    }
X
X    /* resubstitute */
X
X    sub = 1.0/3 * A;
X
X    for (i = 0; i < num; ++i)
X	s[ i ] -= sub;
X
X    return num;
X}
X
X
Xint SolveQuartic(c, s)
X    double c[ 5 ]; 
X    double s[ 4 ];
X{
X    double  coeffs[ 4 ];
X    double  z, u, v, sub;
X    double  A, B, C, D;
X    double  sq_A, p, q, r;
X    int     i, num;
X
X    /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */
X
X    A = c[ 3 ] / c[ 4 ];
X    B = c[ 2 ] / c[ 4 ];
X    C = c[ 1 ] / c[ 4 ];
X    D = c[ 0 ] / c[ 4 ];
X
X    /*  substitute x = y - A/4 to eliminate cubic term:
X	x^4 + px^2 + qx + r = 0 */
X
X    sq_A = A * A;
X    p = - 3.0/8 * sq_A + B;
X    q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
X    r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;
X
X    if (IsZero(r))
X    {
X	/* no absolute term: y(y^3 + py + q) = 0 */
X
X	coeffs[ 0 ] = q;
X	coeffs[ 1 ] = p;
X	coeffs[ 2 ] = 0;
X	coeffs[ 3 ] = 1;
X
X	num = SolveCubic(coeffs, s);
X
X	s[ num++ ] = 0;
X    }
X    else
X    {
X	/* solve the resolvent cubic ... */
X
X	coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
X	coeffs[ 1 ] = - r;
X	coeffs[ 2 ] = - 1.0/2 * p;
X	coeffs[ 3 ] = 1;
X
X	(void) SolveCubic(coeffs, s);
X
X	/* ... and take the one real solution ... */
X
X	z = s[ 0 ];
X
X	/* ... to build two quadric equations */
X
X	u = z * z - r;
X	v = 2 * z - p;
X
X	if (IsZero(u))
X	    u = 0;
X	else if (u > 0)
X	    u = sqrt(u);
X	else
X	    return 0;
X
X	if (IsZero(v))
X	    v = 0;
X	else if (v > 0)
X	    v = sqrt(v);
X	else
X	    return 0;
X
X	coeffs[ 0 ] = z - u;
X	coeffs[ 1 ] = q < 0 ? -v : v;
X	coeffs[ 2 ] = 1;
X
X	num = SolveQuadric(coeffs, s);
X
X	coeffs[ 0 ]= z + u;
X	coeffs[ 1 ] = q < 0 ? v : -v;
X	coeffs[ 2 ] = 1;
X
X	num += SolveQuadric(coeffs, s + num);
X    }
X
X    /* resubstitute */
X
X    sub = 1.0/4 * A;
X
X    for (i = 0; i < num; ++i)
X	s[ i ] -= sub;
X
X    return num;
X}
X
END_OF_FILE
if test 4127 -ne `wc -c <'Roots3And4.c'`; then
    echo shar: \"'Roots3And4.c'\" unpacked with wrong size!
fi
# end of 'Roots3And4.c'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0