# 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

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; { Copyright (c) 2011 James Gunn Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License, as described at http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/ } {$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]'); readln(input); 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?'); readln(input); 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: '); readln(input); 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): '); readln(input); 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: '); readln(input); 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'); readln; //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'); readln; end; until RANDOM_WAVE = false; writeln('Press enter to close'); readln; end.

## Remarks

Could you write a similar program to include waves other than sine waves?