Class SurfaceWave

Smalltalk
Building a Wave Viewer

Wilf LaLonde
Listing 1. Class SurfaceWave.


class:									SurfaceWave
superclass:							Object
instance variables:			grid functionIndex
   class variables:				SpaceWavelength
			SpaceWavelengthInRadians	TimeWavelength
			TimeWavelengthInRadians	Wavelength

class methods

initializing
initialize
	"SurfaceWave initialize"
	self spaceWavelength: 2.0; timeWavelength: 1.0.
	self amplitude: 0.05

wavelength/amplitude
spaceWavelength: aNumber
	 SpaceWavelength := aNumber.
	 SpaceWavelengthInRadians := SpaceWavelength
		 * Float pi * 2.0

spaceWavelength
	 ^SpaceWavelength

spaceWavelengthInRadians
	 ^SpaceWavelengthInRadians

timeWavelength: milliseconds
	 TimeWavelength := milliseconds.
	 TimeWavelengthInRadians := TimeWavelength
		 * 0.001 * Float pi * 2.0

timeWavelength
	 ^TimeWavelength

timeWavelengthInRadians
	 ^TimeWavelengthInRadians

wave functions
function1ForPoint: aPoint time: time
	 "Wave in the x direction."
	 | radians |
	 radians := (aPoint x * self spaceWavelengthInRadians)
		 + (time * self timeWavelengthInRadians).
	 ^radians sin * self amplitude

function2ForPoint: aPoint time: time
	 "Wave in the z direction."
	 | radians |
	 radians := (aPoint z * self spaceWavelengthInRadians)
		 + (time * self timeWavelengthInRadians).
	 ^radians sin * self amplitude

function3ForPoint: aPoint time: time
	 "Wave in the x-z diagonal direction."
	 | radians |
	 radians := ((aPoint x + aPoint z)
		 * self spaceWavelengthInRadians)
		 + (time * self timeWavelengthInRadians).
	 ^radians sin * self amplitude
   
function4ForPoint: aPoint time: time
	 "Wave in the x-z diagonal direction from the center."
	 | radians |
	 radians := ((aPoint x abs + aPoint z abs)
		 * self spaceWavelengthInRadians)
		 + (time * self timeWavelengthInRadians).
	 ^radians sin * self amplitude

function5ForPoint: aPoint time: time
	 "Wave in the x-z diagonal direction from the
	 center growing larger outward."
	 | radians |
	 radians := ((aPoint x abs + aPoint z abs) squared
		 * self spaceWavelengthInRadians)
		 + (time * self timeWavelengthInRadians).
	 ^radians sin * self amplitude

function6ForPoint: aPoint time: time
	 "Wave in the x-z diagonal direction off-center."
	 | radians |
	 radians := (((aPoint x - 0.25) abs + (aPoint z - 0.25) abs)
		 * self spaceWavelengthInRadians)
		 + (time * self timeWavelengthInRadians).
	 ^radians sin * self amplitude

instance methods

initializing
initialize
	 self initializeGrid.
	 self functionIndex: 1

initializeGrid
	 | scale |
	 scale := ([email protected]) / self extent. "For x and z"
	 1 to: self extent x do: [:x |
		 1 to: self extent y do: [:y |
      self at: x@y put:
			 (Point3D x: x*scale x - 0.5 y: 0.0 z: y*scale y - 0.5)]].

get/set
extent: aPoint
	 grid := (1 to: aPoint x) collect: [:x | Array new: aPoint y].
	 self initialize

extent
	 "The grid is an array (1 per x value)
	 of arrays (1 per z value))."
	 ^grid size@grid first size

functionIndex
	 ^functionIndex

functionIndex: anInteger
	 functionIndex := anInteger

functionName
	 ^('function', self functionIndex printString,
	 	 'ForPoint:time:') asSymbol.

2D access
at: aPoint
	 ^(grid at: aPoint x) at: aPoint y
at: aPoint put: aPoint3D
	 ^(grid at: aPoint x) at: aPoint y put: aPoint3D

ticking
advance
	 self functionIndex: self functionIndex + 1.
	 (self class respondsTo: self functionName)
		 ifFalse: [self functionIndex: 1] "wrap"

tick: time
	 | selector aPoint3D |
	 selector := self functionName.
	 1 to: self extent x do: [:x |
		 1 to: self extent y do: [:y |
			 aPoint3D := self at: x@y.
			 aPoint3D y: (self class
				 perform: selector with: aPoint3D with: time)]].

drawing
draw
	 | x1 x2 y1 y2 |
	 "Draw the x lines in red."
	 1 to: self extent y do: [:y |
		 x1 := self at: 1@y.
		 2 to: self extent x do: [:x |
			 x2 := self at: x@y.
			 CanvasLibrary
				 drawLineFrom: x1 x and: x1 y and: x1 z
					 to: x2 x and: x2 y and: x2 z
					 color: 1.0 and: 0.0 and: 0.0 thickness: 2.
			 x1 := x2]].

	 "Draw the z lines in green."
	 1 to: self extent x do: [:x |
		 y1 := self at: x@1.
		 2 to: self extent y do: [:y |
			 y2 := self at: x@y.
			 CanvasLibrary
				 drawLineFrom: y1 x and: y1 y and: y1 z
				 to: y2 x and: y2 y and: y2 z
				 color: 0.0 and: 1.0 and: 0.0 thickness: 2.
			 y1 := y2]]

About the Author

Wilf LaLonde is director of Learning Dimensions, Inc., a company focused on 3D gaming development.