[comp.sources.x] v11i084: xwave, Part01/01

paulr@umbc4.umbc.edu (Paul Riddle) (02/18/91)

Submitted-by: paulr@umbc4.umbc.edu (Paul Riddle)
Posting-number: Volume 11, Issue 84
Archive-name: xwave/part01

---
Xwave plots a perspective projection of a plane grid oscillating in
three-space in real time.
---

This is xwave version 2.0, which contains significant enhancements by
Jim McBeath (jimmc@hisoft.uucp) as well as a few things from us.  The
original is archived as v11i011; since version 2.0 is well over twice
as large, we decided to do a complete repost rather than a patch.

Please refer to the README and the man page for a list of new features,
there are too many to list them all here!

Enjoy,
Paul Riddle (paulr@umbc3.umbc.edu)
Mike Friedman (mikef@umbc3.umbc.edu)
Jim McBeath (jimmc@hisoft.uucp)

----------------------------cut--------------------------------------
#! /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 shell archive."
# Contents:  README xwave.1 Makefile Imakefile patchlevel.h xwave.h
#   force.c plot.c prop.c xwave.c
# Wrapped by X@orion on Sat Feb  9 15:49:03 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1938 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XXwave   Version 2.0   February 4, 1991
X
XXwave plots a perspective projection of a plane grid oscillating in
Xthree-space in real time.  You can select the size of the grid, a
Xforcing function to apply (and where to apply it), and what wave propagation
Xmodel to use.  You can display a plot of the velocity of the points in the
Xgrid as well as the position.
X
XThe original xwave was written by Mike Friedman (mikef@umbc3.umbc.edu)
Xand Paul Riddle (paulr@umbc3.umbc.edu) and posted in January 1991.
XIt was tested under Ultrix 4.0, HP-UX 7.0, and SunOS 4.0.3, and worked
Xon both X11R4 and X11R3 servers.  This version of xwave contains
Xsignificant enhancements by Jim McBeath (jimmc@hisoft.uucp), but has
Xonly been tested on a Sun4 running X11R4.
X
XThe program works best on a risc workstation; if you have something
Xslower, try using the -rows and -cols command line options.
X15 by 15 works pretty well on slower machines.
X
XWhile the program is running, you can use the middle mouse button to move
Xthe plot around, and the left and right mouse buttons to zoom it in and
Xout.  There are many single-key commands you can enter, such as the 'r'
Xcommand to toggle continuous run mode, and space to step through one
Xgeneration.
X
XUsers with color displays can specify the -stereo option.  Be sure to
Xhave your 3-d glasses ready (if you don't have any, you can make
Xthem out of red and blue cellophane :-).  The effect is pretty
Xinteresting.
X
XTry the -demo switch for a quick tour (e.g. "xwave -demo 4").
X
XThere are a many more options; these are all described in the man
Xpage.  Inquiries, bug reports, etc. should be directed to
Xpaulr@umbc3.umbc.edu.
X
XXwave may be freely copied and redistributed in any form, providing
Xthe authors' names stay with the source code.  Let us know if you
Xlike it, improve it, etc.
X
XOriginal Authors:
XMike Friedman (mikef@umbc3.umbc.edu)
XPaul Riddle (paulr@umbc3.umbc.edu)
X
XModified by:
XJim McBeath (jimmc@hisoft.uucp)
END_OF_FILE
if test 1938 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'xwave.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xwave.1'\"
else
echo shar: Extracting \"'xwave.1'\" \(8683 characters\)
sed "s/^X//" >'xwave.1' <<'END_OF_FILE'
X.TH XWAVE 1 "4 February 1991" "X Version 11"
X.SH NAME
Xxwave \- A real-time perspective mesh demo for X
X.SH SYNOPSIS
X.B xwave 
X[
X.I -amp
XA
X]
X[
X.I -bound
Xbits
X]
X[
X.I -cols
XC
X]
X[
X.I -dampfactor
XB
X]
X[
X.I -demo
XnameOrNum
X]
X[
X.I -edit
X]
X[
X.I -force
Xfuncname
X]
X[
X.I -forcecol
XN
X]
X[
X.I -forcefull
X]
X[
X.I -forcepoint
XR C
X]
X[
X.I -forcerow
XN
X]
X[
X.I -omega
XM
X]
X[
X.I -omega2
XM
X]
X[
X.I -plotvel
X]
X[
X.I -printdemo
XnameOrNum
X]
X[
X.I -root
X]
X[
X.I -rows
XR
X]
X[
X.I -springconst
XK
X]
X[
X.I -stereo
X]
X[
X.I -version
X]
X[
X.I -wave
Xfuncname
X]
X
X.SH DESCRIPTION
X.LP
XXwave plots a perspective projection of a plane grid oscillating in
Xthree-space in real time.  You can select the size of the grid, a
Xforcing function to apply (and where to apply it), and what wave propagation
Xmodel to use.  You can display a plot of the velocity of the points in the
Xgrid as well as the position.
XDouble buffering is
Xsimulated using a background pixmap.
XOther options are described below in the "OPTIONS" section.
X.LP
XWhile the wave is being displayed, you can pan and zoom, stop and start
Xupdates, and make other changes.
XThis is described below in the "INTERACTIVE USE" section.
X
X.SH OPTIONS
X.TP
X.B -amp A
XSelect the amplitude of the forcing function.
XTypical numbers are between 20 and 100.
XDefault amplitude is 100.
X.TP
X.B -bound bits
XSelect which corners and edges of the grid are bound and which are free.
XBy default, all corners and edges are bound.
XIf you specify a single "0" or "1" as the argument to -bound, it applies to
Xall eight corners and edges.
XOtherwise, each character in the string applies to one corner or edge: if
Xthat character is "0", the corresponding corner or edge is free; else it is
Xbound.
XThe sequence of corners and edges in the string is: lrlc, lr, lrhc, hc,
Xhrhc, hr, hrlc, lc, where l is low, h is high, r is row, and c is column.
XFor example, -bound "00111000" means the high column end of the grid,
Xincluding those corners, are bound, and all other corners and edges are free.
X.TP
X.B -cols C
XSpecify how many columns are in the grid.
XThe minimum number of columns is 2.
XLarger numbers give more detailed  wave displays,
Xbut take longer to compute and thus do not update as quickly.
XThe default is 25.
X.TP
X.B -dampfactor B
XSpecify the damping factor used in the "wave" propagation model.
XSee the -wave switch for more details.
XThe default is 0.001.
X.TP
X.B -demo nameOrNum
XSelect a demonstration to run.
XEach demo is equivalent to a specific set of switches (which you can see
Xwith the -printdemo command line option).
XFor a quick tour of the program, run "xwave -demo N" starting with N=0 and
Xincrementing until it tells you there are no more demos.
X.TP
X.B -edit
XAllows the user to interactively shape the wave while the program is running.
XWhen the program is in edit mode, the mouse controls an X-shaped cursor that
Xmoves over the surface of the grid.  Position the cursor to where you want
Xto modify the wave and press and hold the left mouse button.  At this point,
Xdragging the mouse up and down will modify the amplitude of the wave and
Xdragging it left and right will control the frequency.  Releasing the mouse
Xbutton will allow you to modify additional points.  When you are finished
Xediting points, press the right mouse button to enter continuous run mode.
X.TP
X.B -force funcname
XSpecify the name of the forcing function to use.
XThis can also be changed interactively (see the INTERACTIVE USE section).
X.TP
X.B -forcecol C
XSpecify that the selected forcing function is to be
Xapplied to all grid points in the specified column.
X(The multisine forcing function ignores this information.)
X.TP
X.B -forcefull
XSpecify that forcing functions which do not cover the full cycle should
Xforce a zero value during the remainder of the cycle.
XBy default, the forcing function takes no action during this part of the
Xcycle, but lets the point move freely.
XThis affects the following forcing functions:
Xdelta, pulse, onehalfsine, onehalfsinesquared.
X.TP
X.B -forcepoint R C
XSpecify that the selected forcing function is to be
Xapplied to the specified grid point.
X(The multisine forcing function ignores this information.)
X.TP
X.B -forcerow R
XSpecify that the selected forcing function is to be
Xapplied to all grid points in the specified row.
X(The multisine forcing function ignores this information.)
X.TP
X.B -omega M
XSpecify a frequency multiplier for forcing functions.
XA larger number makes the forcing functions cycle through their values faster.
X.TP
X.B -omega2 M
XSpecify a secondary frequency multiplier.
XThis number is used in the following forcing functions:
Xpulse, onehalfsine, onehalfsinesquared.
XIf "-omega2 1" is specified, each of these functions will have a duty
Xcycle of 1/2; if "-omega 2" is specifed, it will be 1/4, etc.
X.TP
X.B -plotvel
XSpecify that a plot of the velocity of each point in the grid should appear
Xbelow the plot of the position of each point in the grid.
XThe velocity information is updated only by the "wave" propagation function.
X.TP
X.B -printdemo nameOrNum
XPrint the switches that comprise the specified demo, then exit.
X.TP
X.B -root
XPlot the wave in the root window.
X.TP
X.B -rows R
XSpecify how many rows are in the grid.
XThe minimum number of rows is 2.
XLarger numbers give more detailed  wave displays,
Xbut take longer to compute and thus do not update as quickly.
XThe default is 18.
X.TP
X.B -springconst K
XSpecify the spring constant to use in the "wave" propagation function.
XSee the -wave switch for more details.
XThe default is 0.01.
X.TP
X.B -stereo
XPlot separate projections in red and blue.  Make sure you have your
X3-d glasses handy.  You also need a color display (obviously).
X.TP
X.B -version
XPrints the current version of xwave and exits.
X.TP
X.B -wave funcname
XSpecify the name of the wave propagation function to use.
XYou can specify none, which allows you to see the "naked" forcing function.
XYou can specify relax, which gives a pleasant demo with the multisine
Xforcing function (the original xwave program).
XYou can specify wave, which uses a physical wave propagation model.
XIn the wave model, each point has a mass of 1 and a velocity as well as a
Xposition.
XA simple spring model is used, F = -K*x -B*v, where K is the spring constant
X(specified with -springconst) and B is the damping factor (specified with
X-dampfactor).
XThe distance used for x is the simple vertical distance between a point and
Xits neighbors.
XNote that since this is a discreet simulation, the simulation is
Xhighly dispersive (low frequencies travel faster),
Xso single pulses do not travel very well.
XHowever, you can still see the effects of reflection against a free or
Xbound end, set up nice standing waves, see how the velocity is out of
Xphase with the position, etc.
X
X.SH "INTERACTIVE USE"
X.LP
XWhile xwave is running, you can change the perspective by using the mouse
Xbuttons.
XYou can pan the picture as it is running by holding down the middle mouse
Xbutton and moving the mouse.
XYou can zoom in and out by holding down the left or right mouse buttons.
X(Note that these operations do not work unless xwave is running in
Xcontinuous run mode.)
X.LP
XThere are a number of single-key keyboard commands you can enter into
Xthe graphics window of xwave.
XThese commands can be entered whether or not xwave is in continuous run mode.
XIf the command is not understood, the bell is rung.
XNote that there may be a bit of delay in processing a keyboard command when
Xthe program is in continuous run mode.
X.TP
X.B c
XClear the data and reset the forcing function time; everything starts over
Xagain.
X.TP
X.B d
XLoad the forcing function data.
XThis is useful when in step mode.
X.TP
X.B f
XSelect a different forcing function.
XThe new forcing function name is printed out.
X.TP
X.B p
XPrint out data.
XPrints out all velocity and position data which is non-zero.
XMainly useful in step mode for debugging.
X.TP
X.B q
XQuit the program.
X.TP
X.B r
XToggle run/step mode.
XIn run mode, the program runs continuously and updates the screen.
XThis consumes 100% of the available cpu time, and looks nice.
XIn step mode, you can step through each generation by pressing the
Xspace bar, and see in detail how the grid changes at each step.
XBy default, the program comes up in continuous run mode.
X.TP
X.B t
XToggle timing mode.
XWhen the program is in time mode, it prints an approximation of how many
Xframes per second it is displaying.  This is re-calculated and printed
Xevery 50 frames.
X.TP
X.B w
XSelect a different wave propagation function.
XThe new propagation function name is printed out.
X.TP
X.B <space>
XStep (when in step mode).
XCalculates and displays the grid at the next time point.
X
X.SH AUTHORS
X.LP
XPaul Riddle (paulr@umbc3.umbc.edu)
X.br
XMike Friedman (mikef@umbc3.umbc.edu)
X.br
XJim McBeath (jimmc@hisoft.uucp)
X
END_OF_FILE
if test 8683 -ne `wc -c <'xwave.1'`; then
    echo shar: \"'xwave.1'\" unpacked with wrong size!
fi
# end of 'xwave.1'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(261 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCC = cc
X#CFLAGS = -O
XCFLAGS = -g
X#LDFLAGS = -s
XLDFLAGS = -g
XSRCS = xwave.c force.c plot.c prop.c
XOBJS = xwave.o force.o plot.o prop.o
XLIBS = -lm -lX11
X
Xxwave:	$(OBJS)
X	$(CC) $(LDFLAGS) -o xwave $(OBJS) $(LIBS)
X
X$(OBJS): xwave.h
X
X.o:	$*.c
X	$(CC) $(CFLAGS) -c $@
END_OF_FILE
if test 261 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(188 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
X        DEPLIBS = $(DEPXLIB)
XLOCAL_LIBRARIES = $(XLIB)
X  SYS_LIBRARIES = -lm
X	   SRCS = xwave.c force.c plot.c prop.c
X	   OBJS = xwave.o force.o plot.o prop.o
X
XComplexProgramTarget(xwave)
END_OF_FILE
if test 188 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(776 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define VERSION 2
X#define PATCHLEVEL 0
X#define VDATE "Febuary 1, 1991"
X
X/* Version 2.0: February 1, 1991
X * Extensive mods by Jim McBeath (jimmc@hisoft.uucp):
X *
X * Add multiple wave propagation model capability, plus spring model.
X * Add multiple forcing function capability, plus numerous simple
X *  forcing functions (delta, pulse, sine, etc.).
X * Add lots of command line switches to specify where forcing function
X *  is applied, size of grid, etc.
X * Add boundary conditions: allow edges and corners to be separately
X *  specified as bound or free.
X * Lots of other little changes and code rearrangement.
X *
X * February 9, 1990 - Mike Friedman & Paul Riddle
X * Added interactive editing and timing functions
X * Improved the 3-d effect provided by the -stereo option
X */
END_OF_FILE
if test 776 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'xwave.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xwave.h'\"
else
echo shar: Extracting \"'xwave.h'\" \(695 characters\)
sed "s/^X//" >'xwave.h' <<'END_OF_FILE'
X/* xwave.h - include file for xwave
X *
X */
X
X/* used scaled-up fixed point numbers for more resolution */
X#define SCALE 1024
X
X#define IX(r,c) ((r)*maxcols + (c))
X
X/* structure used to store the data values in the grid of points */
Xtypedef struct pinfo {
X	int pos;	/* current vertical position */
X	int vel;	/* current vertical velocity */
X	int tx,ty;	/* transformed (x,y) point for plotting */
X} Pinfo;
X
Xtypedef struct ftab {
X	char *name;	/* name of the function */
X	int (*func)();	/* pointer to the function */
X} Ftab;
X
Xextern int maxrows, maxcols;
X
Xextern double springconst;
Xextern double dampfactor;
X
Xextern Pinfo *Generation[];
Xextern Pinfo *CurGen;
Xextern Pinfo *NextGen;
X
X/* end */
X
X
X
X
X
X
X
X
END_OF_FILE
if test 695 -ne `wc -c <'xwave.h'`; then
    echo shar: \"'xwave.h'\" unpacked with wrong size!
fi
# end of 'xwave.h'
fi
if test -f 'force.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'force.c'\"
else
echo shar: Extracting \"'force.c'\" \(4788 characters\)
sed "s/^X//" >'force.c' <<'END_OF_FILE'
X/* force.c - forcing functions for xwave
X * multi-sine function by Friedman and Riddle; the rest by McBeath.
X */
X
X#include <stdio.h>
X#include "xwave.h"
X
Xextern int fftime;
Xextern double sinTab[];
Xextern int sinTabSize;
Xextern int omega;
Xextern int omega2;
Xextern int forcerow, forcecol;
Xextern int forceptr, forceptc;
Xextern int forcefull;
Xextern int *editedRowVals;
Xextern int *editedColVals;
Xextern int *amplitudes;
Xextern int *frequencies;
Xextern int didedit;
Xextern int numEditedPoints;
X
X
Xint ForceIndex;
Xint (*ForceFunc)();
X
Xint ampl = 100;
X
Xint ampl1 = 150*SCALE, ampl2 = 100*SCALE;
Xint inc1 = -1, inc2 = -1;
X
X/* original forcing function by Friedman and Riddle */
XForceFuncMultiSine()
X{
X	int t;
X	int row,col,i;
X
X	t = (fftime++)%sinTabSize;
X/* make the assignment only if row and col are in range */
X#define CLOAD(r,c)  if (r<maxrows && c<maxcols) CurGen[IX(r,c)].pos
X
X/* load freq. and amp. matrices */
X#define FVAL(r,c)   frequencies[r*maxcols+c]
X#define AVAL(r,c)   amplitudes[r*maxcols+c]
X
X        if (!didedit) {
X   	       /* Load some of the cells */
X   	           CLOAD(1,2)   = (int)(ampl1*sinTab[(30*t)%sinTabSize]);
X	           CLOAD(2,4)   = (int)(ampl2*sinTab[(25*t)%sinTabSize]);
X	           CLOAD(1,6)   = (int)(ampl1*sinTab[19*(10+t)%sinTabSize]);
X	           CLOAD(2,8)   = (int)(ampl2*sinTab[(20*t)%sinTabSize]);
X	           CLOAD(15,8)  = (int)(ampl2*sinTab[(5*t)%sinTabSize]);
X	           CLOAD(7,10)  = (int)(ampl2*sinTab[(30*t)%sinTabSize]);
X	           CLOAD(9,14)  = (int)(ampl2*sinTab[(20*t)%sinTabSize]);
X	           CLOAD(12,16) = (int)((ampl2+50)*sinTab[(3*t)%sinTabSize]);
X	           CLOAD(7,3)   = (int)(ampl2*sinTab[(40*t)%sinTabSize]);
X
X  	      /* Increment and/or decrement our amplitudes */
X	           if (ampl2 == 0)
X		        inc2 = 5*SCALE;
X	           else if (ampl2 == 350*SCALE)
X		        inc2 = -1*SCALE;
X	           ampl2 += inc2;
X	           if (ampl1 == 0)
X		        inc1 = 5*SCALE;
X	           else if (ampl1 == 200*SCALE)
X		        inc1 = -1*SCALE;
X	           ampl1 += inc1;
X	}
X        else {  /* wave the edited points instead of set points */
X                  row = editedRowVals[0];
X                  col = editedColVals[0];
X                  for (i=0;i<numEditedPoints;i++) {
X                     row = editedRowVals[i];
X                     col = editedColVals[i];
X                     CurGen[row*maxcols+col].pos = (int)(AVAL(row,col)*SCALE*
X                                         sinTab[(FVAL(row,col)*t)%sinTabSize]);
X		  }
X	}
X}
X
XForceX(x)
Xint x;
X{
X	int r,c;
X
X	if (forcerow>=0) {
X		for (c=0; c<maxcols; c++) {
X			CurGen[IX(forcerow,c)].pos = x;
X			CurGen[IX(forcerow,c)].vel = 0;
X		}
X	}
X	if (forcecol>=0) {
X		for (r=0; r<maxrows; r++) {
X			CurGen[IX(r,forcecol)].pos = x;
X			CurGen[IX(r,forcecol)].vel = 0;
X		}
X	}
X	if (forceptr>=0) {
X		CurGen[IX(forceptr,forceptc)].pos = x;
X		CurGen[IX(forceptr,forceptc)].vel = 0;
X	}
X}
X
XForceSine()
X{
X	int t;
X	int x;
X
X	t = (omega*fftime++)%sinTabSize;
X	x = (int)(ampl*SCALE*sinTab[t]);
X	ForceX(x);
X}
X
XForceDelta()
X{
X	int t;
X	int x;
X
X	t = (omega*fftime++)%sinTabSize;
X	if (t==0)
X		x = (int)(ampl*SCALE);
X	else {
X		if (!forcefull) return;
X		x = 0;
X	}
X	ForceX(x);
X}
X
XForcePulse()
X{
X	int t,t2;
X	int x;
X
X	t = (omega*fftime++)%sinTabSize;
X	t2 = omega2*t;
X	if (t2<=sinTabSize/2)
X		x = ampl*SCALE;
X	else {
X		if (!forcefull) return;
X		x = 0;
X	}
X	ForceX(x);
X}
X
XForceOneHalfSine()
X{
X	int t,t2;
X	int x;
X	int r,c;
X
X	t = (omega*fftime++)%sinTabSize;
X	t2 = omega2*t;
X	if (t2<sinTabSize/2)
X		x = (int)(ampl*SCALE*sinTab[t2]);
X	else {
X		if (!forcefull) return;
X		x = 0;
X	}
X	ForceX(x);
X}
X
XForceOneHalfSineSquared()
X{
X	int t,t2;
X	int x;
X	int r,c;
X
X	t = (omega*fftime++)%sinTabSize;
X	t2 = omega2*t;
X	if (t2<sinTabSize/2)
X		x = (int)(ampl*SCALE*sinTab[t2]*sinTab[t2]);
X	else {
X		if (!forcefull) return;
X		x = 0;
X	}
X	ForceX(x);
X}
X
XFtab ForceTab[] = {
X	{ "multisine", ForceFuncMultiSine },
X	{ "delta", ForceDelta },
X	{ "pulse", ForcePulse },
X	{ "sine", ForceSine },
X	{ "onehalfsine", ForceOneHalfSine },
X	{ "onehalfsinesquared", ForceOneHalfSineSquared },
X};
Xint ForceTabSize = sizeof(ForceTab)/sizeof(ForceTab[0]);
X
XInitForceFunc()
X{
X	ForceIndex = 0;
X	ForceFunc = ForceTab[ForceIndex].func;
X}
X
XPrintForceFuncs(fp)
XFILE *fp;
X{
X	int i;
X
X	fprintf(fp,"Forcing functions are:\n");
X	for (i=0; i<ForceTabSize; i++) {
X		fprintf(fp," %s",ForceTab[i].name);
X	}
X	fprintf(fp,"\n");
X}
X
XSetNextForceFunc()
X{
X	ForceIndex++;
X	if (ForceIndex>=ForceTabSize) ForceIndex = 0;
X	ForceFunc = ForceTab[ForceIndex].func;
X	printf("Forcing function is set to %s\n",
X		ForceTab[ForceIndex].name);
X}
X
XSetNamedForceFunc(s)
Xchar *s;
X{
X	int i;
X
X	for (i=0; i<ForceTabSize; i++) {
X		if (strcmp(ForceTab[i].name,s)==0) {
X			ForceIndex = i;
X			ForceFunc = ForceTab[ForceIndex].func;
X			return 1;
X		}
X	}
X	return 0;	/* not found */
X}
X
X/* end */
END_OF_FILE
if test 4788 -ne `wc -c <'force.c'`; then
    echo shar: \"'force.c'\" unpacked with wrong size!
fi
# end of 'force.c'
fi
if test -f 'plot.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'plot.c'\"
else
echo shar: Extracting \"'plot.c'\" \(9847 characters\)
sed "s/^X//" >'plot.c' <<'END_OF_FILE'
X/* plot.c - line drawing and other X functions for xwave.
X * Code here mainly written by Friedman and Riddle,
X * separated into functions by jimmc. Feb '91
X */
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xos.h>
X#include <stdio.h>
X#include "xwave.h"
X
X#define   STARTX     -50
X#define   STARTY     50
X#define   STARTYVOFF 200
X#define   WIDTH      400
X#define   HEIGHT     500
X
Xextern double sqrt();
X
Xextern int flagstereo;
Xextern int flagroot;
Xextern int flagplotvel;
Xextern int flagedit;
X
Xextern int *editedRowVals;
Xextern int *editedColVals;
Xextern int *frequencies;
Xextern int *amplitudes;
Xextern int running;
X
X
XDisplay	*dpy;
Xint screen;
XWindow	win;
X
XColormap cmap;
XXColor red, blue, purple;
X
XGC	gc,gc2;
Xint	scrnWidth = WIDTH, scrnHeight = HEIGHT;
XPixmap  buffer;
X
Xint   FD = 25, PD = 15;
Xint gap = 10;
Xint px= 0, py= 0;
X
Xint numEditedPoints=0;
X
X/* This sets the window up. */
Xvoid InitWindow ()
X{
X	if (!(dpy = XOpenDisplay (""))) {
X		(void) fprintf (stderr, "Error:  Can't open display\n");
X		exit (1);
X	}
X	screen = DefaultScreen (dpy);
X	if (flagroot) {
X		win = DefaultRootWindow (dpy);
X		scrnWidth = DisplayWidth (dpy, screen);
X		scrnHeight = DisplayHeight (dpy, screen);
X	}
X	else {
X		win = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy),
X		    0, 0, scrnWidth, scrnHeight, 1,
X		    WhitePixel (dpy, screen),
X		    BlackPixel (dpy, screen));
X		XSelectInput (dpy, win, ExposureMask | StructureNotifyMask |
X				KeyPressMask);
X		XStoreName (dpy, win, "XWave");
X		XMapWindow (dpy, win);
X	}
X	gc = XCreateGC (dpy, win, 0L, (XGCValues *) 0);
X        gc2= XCreateGC (dpy, win, 0L, (XGCValues *) 0);
X        XSetLineAttributes (dpy,gc2,20,LineSolid,CapButt,JoinMiter);
X        XSetForeground (dpy, gc2, WhitePixel (dpy, screen));
X
X	if (flagstereo)
X		InitColor ();
X	buffer = XCreatePixmap (dpy, DefaultRootWindow (dpy), scrnWidth,
X	    scrnHeight, DefaultDepth (dpy, screen));
X}
X
X/* This loads the red, blue and purple colors into the color map. */
XInitColor ()
X{
X	cmap = DefaultColormap (dpy, screen);
X	blue.red   = 0;
X	blue.blue  = 60000;
X	blue.green = 0;
X
X	red.red   = 40000;
X	red.blue  = 0;
X	red.green = 0;
X
X        purple.red   = 40000;
X        purple.blue  = 60000;
X        purple.green = 0;
X
X
X	if (!(XAllocColor (dpy, cmap, &red)) ||
X	    !(XAllocColor (dpy, cmap, &blue)) ||
X            !(XAllocColor (dpy, cmap, &purple))) {
X		(void) fprintf (stderr, "Error:  Cannot allocate colors\n");
X		exit (1);
X	}
X}
X
XWaitForExpose()
X{
X	/*
X         * Grab an expose event from the server, then we can get started
X         */
X	for (;;) {
X		XEvent event;
X		XNextEvent(dpy, &event);
X		if (event.type == Expose) break;
X	}
X#if 0
X	XWarpPointer (dpy, None, win, 0, 0, 0, 0, scrnWidth / 2,
X	    scrnHeight / 2);
X#endif
X}
X
X/*
X * Perspective projections of points in 3-space to screen coordinates.
X * These are implemented as macros to avoid function call overhead without
X * (well, almost without..) sacrificing readability of the code.
X */
X
X#define xrpers(x,y,z) ((int) (PD - FD * (PD - (x)) / (FD - (z)) + 100))
X#define yrpers(x,y,z) ((int) (FD * (y) / (FD - (z)) + 150))
X#define xlpers(x,y,z) ((int) (-PD - FD * (-PD - (x)) / (FD - (z)) + 100))
X#define ylpers(x,y,z) ((int) (FD * (y) / (FD - (z)) + 150))
X
X/*
X * Line plotting routines.  Again, these are all macros.
X */
X
X#define plotLineRed(x0,y0,z0,x1,y1,z1) \
X   XSetForeground (dpy, gc, red.pixel); \
X   XDrawLine (dpy, buffer, gc, \
X	      xrpers ((float) (x0), (float) (y0), (float) (z0)), \
X	      yrpers ((float) (x0), (float) (y0), (float) (z0)), \
X	      xrpers ((float) (x1), (float) (y1), (float) (z1)), \
X	      yrpers ((float) (x1), (float) (y1), (float) (z1)))
X
X#define plotLineBlue(x0,y0,z0,x1,y1,z1) \
X   XSetForeground (dpy, gc, blue.pixel); \
X   XDrawLine (dpy, buffer, gc, \
X	      xlpers ((float) (x0), (float) (y0), (float) (z0)), \
X	      ylpers ((float) (x0), (float) (y0), (float) (z0)), \
X	      xlpers ((float) (x1), (float) (y1), (float) (z1)), \
X	      ylpers ((float) (x1), (float) (y1), (float) (z1)))
X
X#define plotLine(x0,y0,z0,x1,y1,z1) \
X   if (flagstereo) { \
X      plotLineRed((x0),(y0),(z0),(x1),(y1),(z1)); \
X      plotLineBlue((x0),(y0),(z0),(x1),(y1),(z1)); \
X   } else {\
X      XSetForeground (dpy, gc, WhitePixel (dpy, screen)); \
X      XDrawLine (dpy, buffer, gc, \
X		 xlpers ((float) (x0), (float) (y0), (float) (z0)), \
X		 ylpers ((float) (x0), (float) (y0), (float) (z0)), \
X		 xlpers ((float) (x1), (float) (y1), (float) (z1)), \
X		 ylpers ((float) (x1), (float) (y1), (float) (z1))); \
X   }
X
X/* Plot the current generation in our background pixmap */
XPlotCur(which)
Xint which;		/* 0 means plot position, 1 means plot vel */
X{
X	int r, c;
X	struct pinfo *pi, *pir;
X
X	/* get transformed values for all points in grid */
X	if (which) {	/* velocity */
X		/* velocity stuff added by jimmc */
X		int kscale = (int)(SCALE*sqrt(springconst));
X			/* low spring constant gives smaller velocities, so
X			 * scale up for smaller spring constansts */
X		int startyv = STARTY + STARTYVOFF;
X		for (r = 0; r < maxrows; r++) {
X			for (c = 0; c < maxcols; c++) {
X				pi = CurGen+IX(r,c);
X				pi->tx = gap * c + STARTX + px;
X				pi->ty = pi->vel/kscale + gap * r + startyv+ py;
X			}
X		}
X	} else {	/* position */
X		for (r = 0; r < maxrows; r++) {
X			for (c = 0; c < maxcols; c++) {
X				pi = CurGen+IX(r,c);
X				pi->tx = gap * c + STARTX + px;
X				pi->ty = pi->pos/SCALE + gap * r + STARTY + py;
X			}
X		}
X	}
X
X	/* now plot all the line segments */
X	for (r = 0; r < maxrows - 1; r++) {
X		for (c = 0; c < maxcols - 1; c++) {
X			pi = CurGen+IX(r,c);
X			pir = pi+maxcols;	/* access CurGen[IX(r+1,c)] */
X			/* pi[1] accesses CurGen[IX(r,c+1)] */
X			plotLine (pi->tx, pi->ty, r, pi[1].tx, pi[1].ty, r);
X			plotLine (pi->tx, pi->ty, r, pir->tx, pir->ty, r+1);
X		}
X		/* do the last column (c==maxcols-1) */
X		pi = CurGen+IX(r,c);
X		pir = pi+maxcols;	/* access CurGen[IX(r+1,c)] */
X		plotLine (pi->tx, pi->ty, r, pir->tx, pir->ty, r+1);
X
X	}
X	/* now do the last row (r==maxrows-1) */
X	for (c = 0; c < maxcols - 1; c++) {
X		pi = CurGen+IX(r,c);
X		/* pi[1] accesses CurGen[IX(r,c+1)] */
X		plotLine (pi->tx, pi->ty, r, pi[1].tx, pi[1].ty, r);
X	}
X}
X
XShowData()
X{
X	PlotCur(0);	/* plot the image of the next time point into buffer */
X	if (flagplotvel)
X		PlotCur(1);	/* plot velocity also */
X
X	/* display the buffer we just drew */
X	XCopyArea (dpy, buffer, win, gc, 0, 0, scrnWidth, scrnHeight, 0, 0);
X        if (flagstereo)
X           XSetForeground (dpy, gc, purple.pixel);
X        else
X  	   XSetForeground (dpy, gc, BlackPixel (dpy, screen));
X	XFillRectangle (dpy, buffer, gc, 0, 0, scrnWidth, scrnHeight);
X}
X
XHandleResize(event)
XXEvent *event;
X{
X	if (event->xconfigure.width != scrnWidth ||
X	    event->xconfigure.height != scrnHeight) {
X		XFreePixmap (dpy, buffer);
X		scrnWidth = event->xconfigure.width;
X		scrnHeight = event->xconfigure.height;
X		buffer = XCreatePixmap (dpy, DefaultRootWindow (dpy),
X		    scrnWidth, scrnHeight,
X		    DefaultDepth (dpy, screen));
X		XSetForeground (dpy, gc, BlackPixel (dpy, screen));
X		XFillRectangle (dpy, buffer, gc, 0, 0, scrnWidth, scrnHeight);
X		XSetForeground (dpy, gc, WhitePixel (dpy, screen));
X	}
X}
X
XDoQueryPointer(pxp,pyp)
Xint *pxp, *pyp;
X{
X	static int lastx=0, lasty=0;
X	int thisx, thisy;
X	int dx, dy;
X	int kb;
X	Window junk_win;
X	int junk;
X
X	XQueryPointer (dpy, win, &junk_win, &junk_win, &junk, &junk,
X	    &thisx, &thisy, &kb);
X
X	/*
X	 * Give the user something to do :-)
X	 */
X	if ((kb & Button1Mask) && gap > 10) gap--;
X	if ((kb & Button3Mask) && gap < 50) gap++;
X	if (kb & Button2Mask) {
X		dx = thisx - lastx;
X		dy = thisy - lasty;
X		px += dx;
X		py += dy;
X	}
X	lastx = thisx;
X	lasty = thisy;
X}
X
Xvoid edit ()
X     /* This allows the user to select the wave points and their frequencies */
X{
X  int px,py,junk;
X  Window junkWin;
X  int  x,ax,z,r,c,kb,i;
X  int  xoff,yoff;
X  int  row,col;
X
X  xoff = scrnWidth/2 - 275;
X  yoff = scrnHeight/2 - 350;
X  xoff = 0;
X  yoff = 0;
X
X
X  for (;;) {
X    if (QLength (dpy))
X      ProcessEvent();
X
X    XQueryPointer (dpy, win, &junkWin, &junkWin, &junk, &junk,&px, &py, &kb);
X    if (px<0)
X      px = 0;
X
X    x = (px/10 % maxcols) * gap + STARTX + xoff;
X    ax = px/10 % maxcols;
X    z = (py/10 % (maxrows-1)) + 1;
X    if (z < 1)
X      z = 1;
X
X                /* display the cursor */
X
X    plotLine (x-5,yoff+STARTY+gap*(z-1),z-1, x+5,yoff+STARTY+gap*(z+1),z+1);
X    plotLine (x-5,yoff+STARTY+gap*(z+1),z+1, x+5,yoff+STARTY+gap*(z-1),z-1);
X    plotLine (x-6,yoff+STARTY+gap*(z-1),z-1, x+4,yoff+STARTY+gap*(z+1),z+1);
X    plotLine (x-6,yoff+STARTY+gap*(z+1),z+1, x+4,yoff+STARTY+gap*(z-1),z-1);
X
X
X    if (kb & Button3Mask) { /* right button starts the waving               */
X      flagedit = !flagedit;
X      return;
X    }
X
X    if (kb & Button1Mask) { /* left button held down to change amp. & freq. */
X      while (1) {
X
X        if (QLength (dpy))
X          ProcessEvent();
X
X        for (i=0;i<numEditedPoints;i++) {
X          row = editedRowVals[i];
X          col = editedColVals[i];
X          CurGen[row*maxcols+col].pos = amplitudes[row*maxcols+col];
X        }
X
X        XQueryPointer (dpy,win,&junkWin,&junkWin, &junk, &junk,&px, &py, &kb);
X        XDrawLine (dpy,buffer,gc2,0,scrnHeight-25,px,scrnHeight-25);
X
X        frequencies[z*maxcols+ax] = (int)((float)px / (float)scrnWidth * 32);
X
X        if (frequencies[z*maxcols+ax] < 0)
X          frequencies[z*maxcols+ax] = 0;
X        printf ("frequency=%d  \r",frequencies[z*maxcols+ax]);
X        fflush(stdout);
X
X        if (!(kb & Button1Mask)) {   /* release button to move edit cursor */
X          numEditedPoints++;
X          break;
X        }
X        CurGen[z*maxcols+ax].pos = (py - scrnHeight/2)*SCALE;
X        amplitudes[z*maxcols+ax] = py - scrnHeight/2;
X        editedRowVals[numEditedPoints] = z;
X        editedColVals[numEditedPoints] = ax;
X
X        Step();
X
X        ShowData();
X
X      }
X
X    }
X    Step();
X
X    ShowData();
X
X  }
X}
X
X/* end */
X
END_OF_FILE
if test 9847 -ne `wc -c <'plot.c'`; then
    echo shar: \"'plot.c'\" unpacked with wrong size!
fi
# end of 'plot.c'
fi
if test -f 'prop.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'prop.c'\"
else
echo shar: Extracting \"'prop.c'\" \(8429 characters\)
sed "s/^X//" >'prop.c' <<'END_OF_FILE'
X/* Wave propagation
X * relax prop func by Friedman and Riddle;
X * the rest by jimmc, Feb '91.
X */
X
X#include <stdio.h>
X#include "xwave.h"
X
Xint bound[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
X#define boundlrlc bound[0]
X#define boundlr   bound[1]
X#define boundlrhc bound[2]
X#define boundhc   bound[3]
X#define boundhrhc bound[4]
X#define boundhr   bound[5]
X#define boundhrlc bound[6]
X#define boundlc   bound[7]
X
Xint WaveIndex;
Xint (*WaveFunc)();
X
XCalcBoundedNext()
X{
X	int r, c;
X
X	if (boundlr) {
X		r = 0;
X		for (c=1; c<maxcols-1; c++)
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos;
X	}
X	if (boundhr) {
X		r = maxrows-1;
X		for (c=1; c<maxcols-1; c++)
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos;
X	}
X	if (boundlc) {
X		c = 0;
X		for (r=1; r<maxrows-1; r++)
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos;
X	}
X	if (boundhc) {
X		c = maxcols - 1;
X		for (r=1; r<maxrows-1; r++)
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos;
X	}
X	if (boundlrlc)
X		NextGen[IX(0,0)].pos = CurGen[IX(0,0)].pos;
X	if (boundlrhc)
X		NextGen[IX(0,maxcols-1)].pos = CurGen[IX(0,maxcols-1)].pos;
X	if (boundhrlc)
X		NextGen[IX(maxrows-1,0)].pos = CurGen[IX(maxrows-1,0)].pos;
X	if (boundhrhc)
X		NextGen[IX(maxrows-1,maxcols-1)].pos =
X			CurGen[IX(maxrows-1,maxcols-1)].pos;
X}
X
X/* The trivial case - next generation is exactly like this one (useful for
X * examing the forcing function without having any propagation effects get
X * in the way)
X */
XCalcNone()
X{
X	int r, c;
X
X	for (r = 0; r < maxrows; r++)
X		for (c = 0; c < maxcols; c++)
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos;
X}
X
X/* original propagation model written by Friedman and Riddle.
X * A relaxation model; no velocity component, so no wave propagation;
X * next generation position of each point is independent of current position.
X */
XCalcRelax()
X{
X	int r, c;
X
X	for (r = 1; r < maxrows - 1; r++)
X		for (c = 1; c < maxcols - 1; c++)
X			NextGen[IX(r,c)].pos = (int) (0.25 *
X			    ( CurGen[IX(r - 1,c)].pos
X			    + CurGen[IX(r,c - 1)].pos
X			    + CurGen[IX(r,c + 1)].pos
X			    + CurGen[IX(r + 1,c)].pos));
X
X	/* boundary stuff added by jimmc */
X	if (!boundlr) {
X		r = 0;
X		for (c=1; c<maxcols-1; c++) {
X			NextGen[IX(r,c)].pos = (int) (
X			    ( CurGen[IX(r,c - 1)].pos
X			    + CurGen[IX(r,c + 1)].pos
X			    + CurGen[IX(r + 1,c)].pos) / 3.0 );
X		}
X	}
X	if (!boundhr) {
X		r = maxrows-1;
X		for (c=1; c<maxcols-1; c++) {
X			NextGen[IX(r,c)].pos = (int) (
X			    ( CurGen[IX(r,c - 1)].pos
X			    + CurGen[IX(r,c + 1)].pos
X			    + CurGen[IX(r - 1,c)].pos) / 3.0 );
X		}
X	}
X	if (!boundlc) {
X		c = 0;
X		for (r=1; r<maxrows-1; r++) {
X			NextGen[IX(r,c)].pos = (int) (
X			    ( CurGen[IX(r - 1,c)].pos
X			    + CurGen[IX(r,c + 1)].pos
X			    + CurGen[IX(r + 1,c)].pos) / 3.0 );
X		}
X	}
X	if (!boundhc) {
X		c = maxcols - 1;
X		for (r=1; r<maxrows-1; r++) {
X			NextGen[IX(r,c)].pos = (int) (
X			    ( CurGen[IX(r - 1,c)].pos
X			    + CurGen[IX(r,c - 1)].pos
X			    + CurGen[IX(r + 1,c)].pos) / 3.0 );
X		}
X	}
X	if (!boundlrlc)
X		NextGen[IX(0,0)].pos = (int) (
X		    ( CurGen[IX(1,0)].pos
X		    + CurGen[IX(0,1)].pos) / 2.0 );
X	if (!boundlrhc)
X		NextGen[IX(0,maxcols-1)].pos = (int) (
X		    ( CurGen[IX(1,maxcols-2)].pos
X		    + CurGen[IX(0,maxcols-1)].pos) / 2.0 );
X	if (!boundhrlc)
X		NextGen[IX(maxrows-1,0)].pos = (int) (
X		    ( CurGen[IX(maxrows-2,0)].pos
X		    + CurGen[IX(maxrows-1,1)].pos) / 2.0 );
X	if (!boundhrhc)
X		NextGen[IX(maxrows-1,maxcols-1)].pos = (int) (
X		    ( CurGen[IX(maxrows-2,maxcols-1)].pos
X		    + CurGen[IX(maxrows-1,maxcols-2)].pos) / 2.0 );
X	CalcBoundedNext();
X}
X
X/* wave propagation using simple damped spring model.
X * Spring model is f = - k*x - b*v where k is spring constant, b is damping 
X * factor.
X * x is sum of offsets from four neighbors (to which other end of springs
X * are attached).
X */
XCalcWave()
X{
X	int r, c;
X	int f;
X
X	for (r = 1; r < maxrows - 1; r++) {
X		for (c = 1; c < maxcols - 1; c++) {
X			f = (int) (springconst * (
X			      CurGen[IX(r-1,c)].pos + CurGen[IX(r,c-1)].pos +
X			      CurGen[IX(r,c+1)].pos + CurGen[IX(r+1,c)].pos -
X			      4*CurGen[IX(r,c)].pos) -
X			      dampfactor*CurGen[IX(r,c)].vel);
X			/* a=f/m; assume m=1, so a=f */
X			NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X						NextGen[IX(r,c)].vel;
X		}
X	}
X	if (!boundlr) {
X		r = 0;
X		for (c=1; c<maxcols-1; c++) {
X			f = (int) (springconst * (
X			      CurGen[IX(r,c-1)].pos +
X			      CurGen[IX(r,c+1)].pos + CurGen[IX(r+1,c)].pos -
X			      3*CurGen[IX(r,c)].pos) -
X			      dampfactor*CurGen[IX(r,c)].vel);
X			/* a=f/m; assume m=1, so a=f */
X			NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X						NextGen[IX(r,c)].vel;
X		}
X	}
X	if (!boundhr) {
X		r = maxrows-1;
X		for (c=1; c<maxcols-1; c++) {
X			f = (int) (springconst * (
X			      CurGen[IX(r,c-1)].pos +
X			      CurGen[IX(r,c+1)].pos + CurGen[IX(r-1,c)].pos -
X			      3*CurGen[IX(r,c)].pos) -
X			      dampfactor*CurGen[IX(r,c)].vel);
X			/* a=f/m; assume m=1, so a=f */
X			NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X						NextGen[IX(r,c)].vel;
X		}
X	}
X	if (!boundlc) {
X		c = 0;
X		for (r=1; r<maxrows-1; r++) {
X			f = (int) (springconst * (
X			      CurGen[IX(r+1,c)].pos +
X			      CurGen[IX(r,c+1)].pos + CurGen[IX(r-1,c)].pos -
X			      3*CurGen[IX(r,c)].pos) -
X			      dampfactor*CurGen[IX(r,c)].vel);
X			/* a=f/m; assume m=1, so a=f */
X			NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X						NextGen[IX(r,c)].vel;
X		}
X	}
X	if (!boundhc) {
X		c = maxcols - 1;
X		for (r=1; r<maxrows-1; r++) {
X			f = (int) (springconst * (
X			      CurGen[IX(r+1,c)].pos +
X			      CurGen[IX(r,c-1)].pos + CurGen[IX(r-1,c)].pos -
X			      3*CurGen[IX(r,c)].pos) -
X			      dampfactor*CurGen[IX(r,c)].vel);
X			/* a=f/m; assume m=1, so a=f */
X			NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X			NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X						NextGen[IX(r,c)].vel;
X		}
X	}
X	if (!boundlrlc) {
X		r = 0; c = 0;
X		f = (int) (springconst * (
X		      CurGen[IX(r,c+1)].pos + CurGen[IX(r+1,c)].pos -
X		      2*CurGen[IX(r,c)].pos) -
X		      dampfactor*CurGen[IX(r,c)].vel);
X		/* a=f/m; assume m=1, so a=f */
X		NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X		NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X					NextGen[IX(r,c)].vel;
X	}
X	if (!boundlrhc) {
X		r = 0; c = maxcols-1;
X		f = (int) (springconst * (
X		      CurGen[IX(r,c-1)].pos + CurGen[IX(r+1,c)].pos -
X		      2*CurGen[IX(r,c)].pos) -
X		      dampfactor*CurGen[IX(r,c)].vel);
X		/* a=f/m; assume m=1, so a=f */
X		NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X		NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X					NextGen[IX(r,c)].vel;
X	}
X	if (!boundhrlc) {
X		r = maxrows-1; c = 0;
X		f = (int) (springconst * (
X		      CurGen[IX(r,c+1)].pos + CurGen[IX(r-1,c)].pos -
X		      2*CurGen[IX(r,c)].pos) -
X		      dampfactor*CurGen[IX(r,c)].vel);
X		/* a=f/m; assume m=1, so a=f */
X		NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X		NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X					NextGen[IX(r,c)].vel;
X	}
X	if (!boundhrhc) {
X		r = maxrows-1; c = maxcols-1;
X		f = (int) (springconst * (
X		      CurGen[IX(r,c-1)].pos + CurGen[IX(r-1,c)].pos -
X		      2*CurGen[IX(r,c)].pos) -
X		      dampfactor*CurGen[IX(r,c)].vel);
X		/* a=f/m; assume m=1, so a=f */
X		NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f;
X		NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos +
X					NextGen[IX(r,c)].vel;
X	}
X	CalcBoundedNext();
X}
X
XFtab WaveTab[] = {
X	{ "relax", CalcRelax },
X	{ "wave", CalcWave },
X	{ "none", CalcNone },
X};
Xint WaveTabSize = sizeof(WaveTab)/sizeof(WaveTab[0]);
X
XInitWaveFunc()
X{
X	WaveIndex = 0;
X	WaveFunc = WaveTab[WaveIndex].func;
X}
X
XPrintWaveFuncs(fp)
XFILE *fp;
X{
X	int i;
X
X	fprintf(fp,"Wave propagation functions are:\n");
X	for (i=0; i<WaveTabSize; i++) {
X		fprintf(fp," %s",WaveTab[i].name);
X	}
X	fprintf(fp,"\n");
X}
X
XSetNextWaveFunc()
X{
X	WaveIndex++;
X	if (WaveIndex>=WaveTabSize) WaveIndex = 0;
X	WaveFunc = WaveTab[WaveIndex].func;
X	printf("Wave propagation function is set to %s\n",
X		WaveTab[WaveIndex].name);
X}
X
XSetNamedWaveFunc(s)
Xchar *s;
X{
X	int i;
X
X	for (i=0; i<WaveTabSize; i++) {
X		if (strcmp(WaveTab[i].name,s)==0) {
X			WaveIndex = i;
X			WaveFunc = WaveTab[WaveIndex].func;
X			return 1;
X		}
X	}
X	return 0;	/* not found */
X}
X
XSetBound(s)
Xchar *s;
X{
X	int i;
X	int t;
X
X	if (!s) return;
X	if (strcmp(s,"0")==0) s="00000000";
X	if (strcmp(s,"1")==0) s="11111111";
X	for (i=0; *s && i<8; i++) {
X		bound[i] = (*s++!='0');
X	}
X}
X
X/* end */
END_OF_FILE
if test 8429 -ne `wc -c <'prop.c'`; then
    echo shar: \"'prop.c'\" unpacked with wrong size!
fi
# end of 'prop.c'
fi
if test -f 'xwave.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xwave.c'\"
else
echo shar: Extracting \"'xwave.c'\" \(11740 characters\)
sed "s/^X//" >'xwave.c' <<'END_OF_FILE'
X/******************************************************************************
X** xwave - A 3-d perspective mesh for X
X**
X** Original Authors: (Jan 1991)
X** Mike Friedman (mikef@umbc3.umbc.edu)
X** Paul Riddle (paulr@umbc3.umbc.edu)
X**
X** Additional Help:
X** Joe  Poole  (joe@umbc3.umbc.edu)
X**
X** University of Maryland, Baltimore County
X*
X* Enhanced by Jim McBeath (jimmc@hisoft.uucp) Feb 1991
X******************************************************************************/
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xos.h>
X#include <stdio.h>
X#include <math.h>
X#include "xwave.h"
X#include "patchlevel.h"
X#include <sys/types.h>
X#include <sys/time.h>
X
X
X#define   DFLTMAXROWS    18
X#define   DFLTMAXCOLS    25
X#define   GENS       2
X#define   SINTABSIZE    400
X#define   TWOPI      6.283
X
X#define   NFRAMES    50
X
X#define   ROOT       0x1
X
X#define SPRINGCONST 0.01
X#define DAMPFACTOR 0.001
X
Xextern double atof();
X
Xextern int (*ForceFunc)();
Xextern int (*WaveFunc)();
X
Xextern Display *dpy;
Xextern int ampl;
X
Xextern int numEditedPoints;
X
Xint maxrows = DFLTMAXROWS;
Xint maxcols = DFLTMAXCOLS;
Xint CurIndex = 0;
Xint NextIndex = 1;
Xstruct pinfo *Generation[GENS];
Xstruct pinfo NullPinfo = {0};
Xstruct pinfo *CurGen;
Xstruct pinfo *NextGen;
X
Xint *amplitudes;
Xint *frequencies;
Xint *editedRowVals;
Xint *editedColVals;
X
Xdouble sinTab[SINTABSIZE];
Xint sinTabSize = SINTABSIZE;
X
Xint running = 1;
Xint fftime;
Xint omega=5;
Xint omega2=10;
Xint forcerow = -1;
Xint forcecol = -1;
Xint forceptr = -1;
Xint forceptc = -1;
Xint forcefull = 0;
X
Xdouble springconst = SPRINGCONST;
Xdouble dampfactor = DAMPFACTOR;
X
Xint flagtime=0;
Xint flagstereo=0;
Xint flagroot=0;
Xint flagplotvel=0;
Xint flagedit=0;
Xint didedit=0;
X
Xint nf;
Xint start;
X
X
Xchar *
Xsmalloc(s)
Xint s;
X{
X	extern char *malloc();
X	char *p;
X
X	p = malloc(s);
X	if (p) return p;
X	fprintf(stderr,"No more memory\n");
X	exit(2);
X}
X
Xchar *
Xscalloc(n,s)
Xint n,s;
X{
X	extern char *calloc();
X	char *p;
X
X	p = calloc(n,s);
X	if (p) return p;
X	fprintf(stderr,"No more memory\n");
X	exit(2);
X}
X
Xchar *demoorig[] = { "original" };	/* the original - no args */
Xchar *demodeltapoint[] = { "deltapoint", "-force", "delta", "-wave", "wave",
X	"-omega", "2" };
Xchar *demodeltarow[] = { "deltarow", "-force", "delta", "-wave", "wave",
X	"-forcerow", "8", "-amp", "30", "-omega", "2", "-bound", "0" };
Xchar *demosineh[] = { "sineh", "-force", "onehalfsinesquared", "-wave", "wave",
X	"-rows", "2", "-cols", "50", "-forcecol", "0", "-bound", "00111000",
X	"-omega", "1", "-omega2", "4" };
Xchar *demosine[] = { "sine", "-force", "sine", "-wave", "wave",
X	"-rows", "2", "-cols", "48", "-forcecol", "0", "-bound", "00111000",
X	"-omega", "5", "-plotvel", "-springconst", "0.05" };
Xchar *demopulse[] = { "pulse", "-force", "pulse", "-forcefull", "-wave", "wave",
X	"-omega", "1", "-omega2", "4", "-rows", "2", "-cols", "46",
X	"-forcecol", "0", "-bound", "00111000", "-springconst", "0.05",
X	"-plotvel" };
Xchar *demopulse2[] = { "pulse", "-force", "pulse", "-wave", "wave",
X	"-omega", "2", "-omega2", "4" };
X/* remember to add new demo to demoinfo table below */
X
Xstruct {
X	char **p;
X	int n;
X} demoinfo [] = {
X	{ demoorig, sizeof(demoorig)/sizeof(demoorig[0]) },
X	{ demodeltapoint, sizeof(demodeltapoint)/sizeof(demodeltapoint[0]) },
X	{ demodeltarow, sizeof(demodeltarow)/sizeof(demodeltarow[0]) },
X	{ demosineh, sizeof(demosineh)/sizeof(demosineh[0]) },
X	{ demosine, sizeof(demosine)/sizeof(demosine[0]) },
X	{ demopulse, sizeof(demopulse)/sizeof(demopulse[0]) },
X	{ demopulse2, sizeof(demopulse2)/sizeof(demopulse2[0]) },
X};
Xint demoinfocount = sizeof(demoinfo)/sizeof(demoinfo[0]);
X
Xint
XfindDemo(s)
Xchar *s;
X{
X	int i;
X
X	i = atoi(s);
X	if (i>0 || strcmp(s,"0")==0) {
X		if (i>=demoinfocount) {
X			(void)fprintf(stderr,"Max demo number is %d\n",
X				demoinfocount-1);
X			exit(1);
X		}
X		return i;	/* he specified a number (index) */
X	}
X	for (i=0; i<demoinfocount; i++) {
X		if (strcmp(demoinfo[i].p[0],s)==0)
X			return i;
X	}
X	(void)fprintf(stderr,"No such demo switch %s\n",s);
X	exit(1);
X}
X
XDemoSwitch(s)
Xchar *s;
X{
X	int n;
X
X	n = findDemo(s);
X	ProcessArgs(demoinfo[n].n,demoinfo[n].p);
X}
X
XPrintDemoSwitch(s)
Xchar *s;
X{
X	int i,n;
X
X	n = findDemo(s);
X	for (i=0; i<demoinfo[n].n; i++) {
X		printf("%s ",demoinfo[n].p[i]);
X	}
X	printf("\n");
X	exit(0);
X}
X
XListDemoSwitches(fp)
XFILE *fp;
X{
X	int i;
X
X	fprintf(fp,"Demo switches are:\n");
X	for (i=0; i<demoinfocount; i++) {
X		fprintf(fp," %s", demoinfo[i].p[0]);
X	}
X	fprintf(fp,"\n");
X}
X
XProcessArgs(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int i;
X
X	for (i=1; i<argc; i++) {
X                if (strcmp (argv[i], "-edit")==0) {
X                        flagedit = 1;
X                        didedit = 1;
X		}
X		else if (strcmp (argv[i], "-root")==0)
X			flagroot = 1;
X		else if (strcmp (argv[i], "-stereo")==0)
X			flagstereo = 1;
X		else if (strcmp(argv[i],"-springconst")==0) {
X			springconst = atof(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-dampfactor")==0) {
X			dampfactor = atof(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-rows")==0) {
X			maxrows = atoi(argv[++i]);
X			if (maxrows<2) maxrows = 2;
X                        else if (maxrows>25) maxrows = 25;
X		}
X		else if (strcmp(argv[i],"-cols")==0) {
X			maxcols = atoi(argv[++i]);
X			if (maxcols<2) maxcols = 2;
X		}
X		else if (strcmp(argv[i],"-omega")==0) {
X			omega = atoi(argv[++i]);
X			if (omega<=0) omega=1;	/* can't divide by 0 */
X		}
X		else if (strcmp(argv[i],"-omega2")==0) {
X			omega2 = atoi(argv[++i]);
X			if (omega2<=0) omega2=1;	/* can't divide by 0 */
X		}
X		else if (strcmp(argv[i],"-amp")==0) {	/* forcing amplitude */
X			ampl = atoi(argv[++i]);
X			if (ampl<=0) ampl = 100;
X		}
X		else if (strcmp(argv[i],"-force")==0) {
X			if (!SetNamedForceFunc(argv[++i])) {
X				usage();
X				exit(1);
X			}
X		}
X		else if (strcmp(argv[i],"-forcerow")==0) {
X			forcerow = atoi(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-forcecol")==0) {
X			forcecol = atoi(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-forcepoint")==0) {
X			forceptr = atoi(argv[++i]);
X			forceptc = atoi(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-forcefull")==0) {
X			forcefull = 1;
X		}
X		else if (strcmp(argv[i],"-bound")==0) {
X			SetBound(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-wave")==0) {
X			if (!SetNamedWaveFunc(argv[++i])) {
X				usage();
X				exit(1);
X			}
X		}
X		else if (strcmp(argv[i],"-demo")==0) {
X			DemoSwitch(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-printdemo")==0) {
X			PrintDemoSwitch(argv[++i]);
X		}
X		else if (strcmp(argv[i],"-plotvel")==0) {
X			flagplotvel = 1;
X		}
X		else if (strcmp(argv[i],"-version")==0) {
X			(void)printf("xwave version %d.%d, %s\n",
X				VERSION, PATCHLEVEL, VDATE);
X			exit(0);
X		}
X		else {
X			usage();
X			exit (1);
X		}
X	}
X}
X
XCheckArgs()
X{
X	if (forcerow >= maxrows)
X		forcerow = maxrows/2;
X	if (forcecol >= maxcols)
X		forcecol = maxcols/2;
X	if (forceptr >= maxrows)
X		forceptr = maxrows/2;
X	if (forceptc >= maxcols)
X		forceptc = maxcols/2;
X	if (forcerow<0 && forcecol<0) {
X		if (forceptr<0)
X			forceptr = maxrows/2;
X		if (forceptc<0)
X			forceptc = maxcols/2;
X	} else {
X		forceptr = forceptc = -1;
X	}
X}
X
Xusage()
X{
X	(void)fprintf(stderr, "Usage: xwave [-edit] [-root] [-stereo] [-springconst K]\n");
X	(void)fprintf(stderr, "   [-dampfactor B] [-rows r] [-cols c]\n");
X	(void)fprintf(stderr, "   [-force func] [-wave func] [-bound bits]\n");
X	(void)fprintf(stderr, "   [-omega n] [-omega2 n] [-amp n]\n");
X	(void)fprintf(stderr, "   [-forcerow r] [-forcecol c] [-forcepoint r c]\n");
X	(void)fprintf(stderr, "   [-forcefull]\n");
X	(void)fprintf(stderr, "   [-demo D] [-printdemo D] [-plotvel] [-version]\n");
X	PrintForceFuncs(stderr);
X	PrintWaveFuncs(stderr);
X	ListDemoSwitches(stderr);
X}
X
XAllocData()
X{
X	Generation[0] = (struct pinfo *)smalloc(sizeof(struct pinfo)*
X					maxrows*maxcols);
X	Generation[1] = (struct pinfo *)smalloc(sizeof(struct pinfo)*
X					maxrows*maxcols);
X        amplitudes    = (int *)scalloc(maxrows*maxcols,sizeof(int));
X        frequencies   = (int *)scalloc(maxrows*maxcols,sizeof(int));
X        editedRowVals = (int *)scalloc(maxrows,sizeof(int));
X        editedColVals = (int *)scalloc(maxcols,sizeof(int));
X}
X
XClearData()
X{
X	int r, c, g;
X
X	/* clear the forcing function timer */
X	fftime = 0;
X
X	/* Zero out the generation matrix */
X	for (r = 0; r < maxrows; r++)
X		for (c = 0; c < maxcols; c++)
X			for (g = 0; g<GENS; g++)
X				Generation[g][IX(r,c)] = NullPinfo;
X
X	CurIndex = 0;
X	NextIndex = 1;
X	CurGen = Generation[CurIndex];
X	NextGen = Generation[NextIndex];
X}
X
X/* This routine initializes the sine table.  The table is accessed during
X * computation to speed things up somewhat. */
Xvoid setupSinTable (sinTab)
Xdouble *sinTab;
X{
X	int i;
X	double t = 0.0;
X
X	for (i = 0; i < SINTABSIZE; i++, t += TWOPI / SINTABSIZE)
X		sinTab[i] = sin (t);
X}
X
XDumpCur()
X{
X	int r,c;
X	int v,p;
X
X	for (r = 0; r < maxrows; r++) {
X		for (c = 0; c < maxcols; c++) {
X			v = CurGen[IX(r,c)].vel;
X			p = CurGen[IX(r,c)].pos;
X			if (v!=0 || p!=0)
X				printf("[%d,%d]=(%d,%d)\n",r,c,v,p);
X		}
X	}
X}
X
XProcessKey(s)
Xchar *s;
X{
X	if (strcmp(s,"t")==0) {		/* time # frames */
X                nf=0;
X                flagtime=!flagtime;
X	}
X	else if (strcmp(s,"c")==0) {	/* clear */
X		ClearData();
X		ShowData();
X	}
X	else if (strcmp(s,"d")==0) {	/* (load) data */
X		(*ForceFunc)();
X		ShowData();
X	}
X	else if (strcmp(s,"f")==0) {	/* forcing function */
X		SetNextForceFunc();
X	}
X	else if (strcmp(s,"p")==0) {	/* print data */
X		DumpCur();
X	}
X	else if (strcmp(s," ")==0) {	/* step */
X		Step();
X		ShowData();
X	}
X	else if (strcmp(s,"r")==0)	/* run mode */
X		running = !running;
X	else if (strcmp(s,"q")==0)	/* q to exit */
X		exit(0);
X	else if (strcmp(s,"w")==0) {	/* wave propagation function */
X		SetNextWaveFunc();
X	}
X	else XBell(dpy,25);	/* unknown */
X}
X
XProcessEvent()
X{
X	/*
X	 * Handle resizes.  When a resize happens, we need to re-allocate
X	 * the background pixmap.  Note that the bigger the window, the
X	 * larger the area that needs to get copied, and therefore the
X	 * slower the program gets.
X	 */
X	XEvent event;
X	int t;
X	char cbuf[20];
X
X	XNextEvent (dpy, &event);
X	switch (event.type) {
X	case ConfigureNotify:
X		HandleResize(&event);
X		break;
X	case KeyPress:
X                if (!flagedit) {
X		    t = XLookupString(&event,cbuf,sizeof(cbuf),
X			(KeySym *)NULL, (XComposeStatus *)NULL);
X		    if (t<=0) break;
X                    flagedit = 0;
X                    cbuf[t] = '\0';
X		    ProcessKey(cbuf);
X		    break;
X	        }
X	default:
X		break;
X	}
X}
X
XStep()
X{
X	(*WaveFunc)();	/* calculate values at the next time point */
X	CurIndex ^= 1;	/* swap next and current buffers */
X	NextIndex ^= 1;
X	CurGen = Generation[CurIndex];
X	NextGen = Generation[NextIndex];
X
X	(*ForceFunc)();	/* apply forcing function */
X
X}
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int t;
X
X	InitWaveFunc();
X	InitForceFunc();
X
X	ProcessArgs(argc,argv);
X	CheckArgs();	/* check for consistency etc. */
X	AllocData();
X	ClearData();
X	InitWindow ();
X	setupSinTable (sinTab);
X	if (flagroot)
X		WaitForExpose();
X	while (1) {
X		if (running) {
X                        if (flagtime) {
X                               if (nf==0)
X                                     start = time((time_t)0);
X                               if (nf==NFRAMES) {
X                                     printf("#frames/sec.~%f\n",
X                                            (float)nf/((time((time_t)0)-start)));
X                                     nf = 0;
X                               }
X                               else
X                                     nf++;
X		        }
X			if (QLength (dpy)) {
X				ProcessEvent();
X			}
X			DoQueryPointer();
X                        if (flagedit)
X                                edit();
X			Step();
X			ShowData();
X		}
X		else {
X		        ProcessEvent();
X                        if (flagedit)
X                                edit();
X		}
X	}
X	/* NOTREACHED */
X}
X
X/* end */
X
X
X
X
X
X
X
END_OF_FILE
if test 11740 -ne `wc -c <'xwave.c'`; then
    echo shar: \"'xwave.c'\" unpacked with wrong size!
fi
# end of 'xwave.c'
fi
echo shar: End of shell archive.
exit 0


--
Dan Heller
------------------------------------------------
O'Reilly && Associates 		      Zyrcom Inc
Senior Writer			       President
argv@ora.com			argv@zipcode.com