# WaveInterference

by James Gunn: L6 Age ~16

## Introduction

James has made excellent use of Wingraph and other advanced Pascal features to produce a most effective educational program. It is now available in Smart Pascal as a web preview.

You can input many sine waves with different amplitudes, offsets, and relative frequencies then the program will draw them in different colours. After the drawing is complete, you will probably want to select the console window and press RETURN to instruct the program to calculate and display the sum of all of the waves.

We used the program to construct two waves with the same frequency, a 180 degree phase difference and differing slightly in amplitude with the following input:

Input for destructive interference

The result of adding these waves is a wave with amplitude 10, shown in white:

Destructive interference

We can show summing a low frequency sine wave to a high frequency sine wave with the following input.

Input for low and high frequency waves

The resulting wave is shown in white:

Low and high frequency waves

Alternatively, we can instruct the program to generate random waves to obtain an output such as this.

Random output

The program uses conditional compilation to give a "verbose" option which outputs the properties of the waves on the console. (However, it is not so verbose as to indicate what the numbers represent!)

In order to run program WaveInterference, you will need to have downloaded Stefan Berinde`s wingraph.zip file as described in our Graphics tutorial. You should copy the unzipped wincrt.pas and wingraph.pas (from the src folder) into your program folder. (The compiled units are included in the zip file but you might as well have the source code available for reference). You should find these three files useful for your own graphics programs.

## The Program

```program WaveInterference;
{

use this file except in compliance with the License, as described at
}

{\$APPTYPE CONSOLE}{\$H+}
//{\$define verbose}

uses
Classes, SysUtils, Wingraph, Wincrt, StrUtils;

const
//Here we define how large we want the window to be.
WIN_HEIGHT : integer = 600;
WIN_WIDTH : integer = 600;

var
gd, gm, i, j : smallint;
amp : array of integer;
offset, freq : array of real;
colour : array of integer;
num_waves, sumN, sumF, intInput, intErrorCode : integer;
input : string;
RANDOM_WAVE : boolean = false;

begin
randomize; //so random numbers will work
//gd and gm used later to initiate the WinGraph window
gd := 9;
gm := 13;

//Ask the users if they want random waves, and keep
//doing so until they choose 1 (yes) or 0 (no)
repeat
writeln('Produce random waves? [0 = False, 1 = True]');
val(input, intInput, intErrorCode);
until (intErrorCode = 0) and ((intInput = 1) or (intInput = 0));
//If they did choose a random wave, then we store this information
//in a boolean variable.
if intInput= 1 then
RANDOM_WAVE := true;
writeln;
//Ask the user how many waves they are going to want
repeat
writeln('How many waves per run?');
val(input, intInput, intErrorCode);
until (intErrorCode = 0) and (intInput >0 );
//and store it in a variable.
num_waves := intInput;
//Extend the arrays to fit the number of waves
//the user has specified'
SetLength(amp, num_waves);
SetLength(offset, num_waves);
SetLength(colour, num_waves);
SetLength(freq, num_waves);
writeln;
repeat
//Clear the device for use.
ClearDevice;
//Loop through the number of waves
for i := 0 to num_waves - 1 do
begin
//Now check if we are running in verbose mode. If we are then
//we need to print out all of the wave details to the screen.
{\$ifdef verbose}
write('Wave ', i + 1, ':');
{\$endif}

//Generate a random amplitude for the wave between 25 and 150 if we are
//running in random wave mode.
//If we are running in verbose mode then output the result to the console.
if RANDOM_WAVE then
begin
amp[i] := random(150) + 25;
{\$ifdef verbose}
write(' ', Round(amp[i]));
{\$endif}
end
else
//If we are not running in verbose mode then allow the user to enter
//the wave amplitude and then validate the entry.
begin
repeat
writeln;
write('Amplitude: ');
val(input, intInput, intErrorCode);
until (intErrorCode = 0) and (intInput > 0);
amp[i] := intInput;
end;

//We now do the same for offset
if RANDOM_WAVE then
begin
offset[i] := random(360);
{\$ifdef verbose}
write(' ', Round(offset[i]));
{\$endif}
end
else
begin
repeat
write('Offset (Degrees): ');
val(input, intInput, intErrorCode);
until (intErrorCode = 0) and (intInput >= 0);
offset[i]:=intInput * pi / 180;
end;

//and again for the frequency multiplier.
if RANDOM_WAVE then
begin
freq[i]:=(random(50) / 10) + 1;
{\$ifdef verbose}
writeln(' ', Round(freq[i]));
{\$endif}
end
else
begin
repeat
write('Frequency Multiplier: ');
val(input, intInput, intErrorCode);
until (intErrorCode = 0) and (intInput > 0);
freq[i] := intInput;
end;
//Here the wave is given a random colour. It is fixed to give a light colour.
colour[i]:=(random(155) + 100) + (random(155) + 100) * 256 + (random(200) + 55) * 256 * 256;
end;
//Now set up the window according to the constants
//and add a title so everyone knows who created it.
setwindowsize(WIN_WIDTH, WIN_HEIGHT);
initgraph(gd, gm, 'Wave Adder v2.0 James Gunn');
//Draw the axis.
MoveTo(1, ((WIN_HEIGHT div 2) - 50));
LineTo(WIN_WIDTH, ((WIN_HEIGHT div 2) - 50));

//Loop through all x-values and waves to draw each wave.
for i := 0 to WIN_WIDTH do
begin
//Loop through all of the waves that have been set up (could be random or user defined).
for j := 0 to num_waves - 1 do
begin
//Set the colour to draw the wave as the colour generated above.
SetColor(colour[j]);
//Calculate the y-value of the wave at the current x-value (i) based on the
//amplitude, frequency and offset.
MoveTo(i, Round(Sin(((i * pi / 180) * freq[j]) + offset[j]) * amp[j]) + ((WIN_HEIGHT div 2) - 50));
//Calculate the y-value for the next x-value and draws the line between
//them, thereby drawing the first section of the wave.
LineTo(i + 1, Round(Sin((((i + 1) * pi / 180) * freq[j]) + offset[j]) * amp[j]) + ((WIN_HEIGHT div 2) - 50));
end;
delay(5) ;
end;
writeln('Press enter to see the sum');
//Change the colour to white to make the sum stand out.
SetColor(white);
for i:= 0 to WIN_WIDTH do
begin
sumN := 0;
sumF := 0;
//Add up the y-value of all waves at the current x-value.
for j := 0 to num_waves - 1 do
sumN := sumN + Round(Sin((( i * pi / 180) * freq[j]) +  offset[j]) * amp[j]);
//Add up the y-value of all waves at the next x-value.
for j := 0 to num_waves-1 do
sumF := sumF + Round(Sin((((i + 1) * pi / 180) * freq[j]) + offset[j]) * amp[j]);
MoveTo(1, ((WIN_HEIGHT div 2) - 50));
LineTo(WIN_WIDTH, ((WIN_HEIGHT div 2) - 50));
//The sum is only drawn if there are 2 or more waves.
if num_waves > 1 then
begin
//Using the sums calculated above, draw each section of the sum wave.
MoveTo(i, sumN + ((WIN_HEIGHT div 2) - 50 ));
LineTo(i + 1, sumF + ((WIN_HEIGHT div 2) - 50));
end;
delay(5);
end;
if RANDOM_WAVE = true then
begin
writeln('Press enter to run again');