Web Version of WaveInterference

Smart Pascal version of WaveInterference by James Gunn

Introduction

Click on the green up arrow at the foot of the page to see the original program. If the program does not work in your current browser, try another such as Chrome. If you see no display at school, the security system might have blocked it. You can try instead this direct link to the program running on its own page. The Smart Pascal code of the form unit and the XML code of the form follow.

Program in Action

WaveInterference.html

Code of Unit Form1

unit Form1;
{
    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/

    Converted to Smart Pascal for web preview by PPS 2014
}

interface

uses
  SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms,
  SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.PaintBox,
  SmartCL.Controls.EditBox, SmartCL.Controls.Label, SmartCL.Controls.CheckBox,
  SmartCL.Controls.Button, SmartCL.Controls.Listbox, System.Colors;

type
  TForm1 = class(TW3Form)
    procedure btnViewClick(Sender: TObject);
  private
    {$I 'Form1:intf'}
    inputs : array[0..11] of TW3EditBox;
    amp : array of integer;
    offset, freq : array of float;
    colour : array of integer;
    num_waves, sumN, sumF : integer;
    RANDOM_WAVE : boolean = false;
  protected
    procedure InitializeForm; override;
    procedure InitializeObject; override;
    procedure SetUpEditBoxes;
    procedure ShowEditBoxes;
    procedure ReadEditBoxes;
  end;

implementation

procedure TForm1.SetUpEditBoxes;
begin
  for var i := 0 to 11 do
    begin
      inputs[i] := new TW3EditBox(self);
      inputs[i].Width := 40;
      inputs[i].Height := 32;
      inputs[i].Left := 300 + (i div 3) * 48;
      inputs[i].Top := 32 *(i mod 3);
      inputs[i].text := '';
      inputs[i].visible := true;
    end;
end;

procedure TForm1.ShowEditBoxes;
begin
  for var i := 0  to 11 do
    if i < num_waves * 3  then
     inputs[i].visible := true
   else
     inputs[i].visible := false;
end;

procedure TForm1.ReadEditBoxes;
begin
  for var i := 0  to num_waves * 3 - 1 do
    case i mod 3 of
      0 : amp[i div 3] := strToint(inputs[i].text);
      1 : offset[i div 3] := strTofloat(inputs[i].text) * pi / 180;
      2 : freq[i div 3] := strTofloat(inputs[i].text);
    end;
end;

procedure TForm1.btnViewClick(Sender: TObject);
begin
  pb.Canvas.FillStyle := 'lightblue';
  pb.Canvas.FillRect(0, 0, pb.Width, pb.Height);
  //Extend the arrays to fit the number of waves the user has specified
  amp.SetLength(num_waves);
  offset.SetLength(num_waves);
  colour.SetLength(num_waves);
  freq.SetLength(num_waves);
  RANDOM_WAVE := chkRandom.Checked;
  // Generate a random amplitude for the wave between 25 and 50 if we are
  // running in random wave mode.
  for var i := 0 to num_waves - 1 do
    begin
      colour[i] := (randomInt(155) + 100) + (randomInt(155) + 100) * 256 + (randomInt(200) + 55) * 256 * 256;
      if RANDOM_WAVE then
        begin
          amp[i] := randomInt(50) + 25;
          freq[i] := (randomInt(50) / 10) + 1;
          offset[i] := randomInt(360) * pi / 180;
        end
    end;
  if not RANDOM_WAVE then
    ReadEditBoxes;
  //Draw the axis.
  pb.Canvas.beginPath;
  pb.Canvas.StrokeStyle := 'white';
  pb.Canvas.MoveToF(1, pb.Height div 2);
  pb.Canvas.LineToF(pb.Width, pb.Height div 2);
  pb.Canvas.Stroke;

  for var i := 0 to pb.Width do
    begin
      //Loop through all of the waves that have been set up (could be random or user defined).
      for var j := 0 to num_waves - 1 do
        begin
          pb.Canvas.beginPath;
          //Set the colour to draw the wave as the colour generated above.
          pb.Canvas.StrokeStyle := ColorToWebStr(colour[j]);
          //Calculate the y-value of the wave at the current x-value (i) based on the
          //amplitude, frequency and offset.
          pb.Canvas.MoveToF(i, Round(Sin(((i * pi / 180) * freq[j]) + offset[j]) * amp[j]) + pb.Height div 2);
          //Calculate the y-value for the next x-value and draws the line between
          //them, thereby drawing the first section of the wave.
          pb.Canvas.LineToF(i + 1, Round(Sin((((i + 1) * pi / 180) * freq[j]) + offset[j]) * amp[j]) + pb.Height div 2);
          pb.Canvas.Stroke;
        end;
    end;
  pb.Canvas.StrokeStyle := 'white';
  pb.Canvas.beginpath;
  for var i:= 0 to pb.Width do
    begin
      sumN := 0;
      sumF := 0;
      //Add up the y-value of all waves at the current x-value.
      for  var 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 var j := 0 to num_waves-1 do
        sumF := sumF + Round(Sin((((i + 1) * pi / 180) * freq[j]) + offset[j]) * amp[j]);
      pb.Canvas.MoveToF(1, pb.Height div 2);
      pb.Canvas.LineToF(pb.Width, pb.Height div 2);
      //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.
          pb.Canvas.MoveToF(i, sumN + pb.Height div 2);
          pb.Canvas.LineToF(i + 1, sumF + pb.Height div 2);
        end;
      pb.Canvas.Stroke;
    end;
end;

procedure TForm1.InitializeForm;
begin
  inherited;
  SetUpEditBoxes;
  ShowEditBoxes;
end;

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  Randomize;
  num_waves := 2;
  W3ListBox1.ItemClass := TW3Label;
  W3ListBox1.Add;
  W3ListBox1.Add;
  W3ListBox1.Add;
  W3ListBox1.Styles.SelectedColor := clLightBlue;
  W3ListBox1.SelectedIndex := 0;
  W3ListBox1.ItemHeight := 20;
  W3ListBox1.SetSize(30, 75);
  W3ListBox1.EnableAnimation := false;
  W3ListBox1.OnSelected := procedure (sender: TObject; idx: integer)
    begin
      num_waves := idx + 2;
      ShowEditBoxes;
    end;
  TW3Label(W3ListBox1.Items[0]).Caption:= '2';
  TW3Label(W3ListBox1.Items[1]).Caption:= '3';
  TW3Label(W3ListBox1.Items[2]).Caption:= '4';
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TForm1);
end.

XML Code of Form

<SMART>
  <Form version="2" subversion="1">
    <Created>2014-10-15T18:34:53.620</Created>
    <Modified>2014-10-18T17:29:25.401</Modified>
    <object type="TW3Form">
      <Caption>W3Form</Caption>
      <Name>Form1</Name>
      <object type="TW3PaintBox">
        <Width>750</Width>
        <Top>104</Top>
        <Height>600</Height>
        <Name>pb</Name>
      </object>
      <object type="TW3Label">
        <Caption>Waves Per Run</Caption>
        <Width>128</Width>
        <Height>32</Height>
        <Name>W3Label1</Name>
      </object>
      <object type="TW3Label">
        <Caption>Amplitudes</Caption>
        <Width>128</Width>
        <Left>128</Left>
        <Height>32</Height>
        <Name>W3Label2</Name>
      </object>
      <object type="TW3CheckBox">
        <Caption>Random Waves</Caption>
        <Width>128</Width>
        <Top>8</Top>
        <Left>596</Left>
        <Height>32</Height>
        <Name>chkRandom</Name>
      </object>
      <object type="TW3Label">
        <Caption>Offsets</Caption>
        <Width>56</Width>
        <Top>32</Top>
        <Left>128</Left>
        <Height>32</Height>
        <Name>W3Label3</Name>
      </object>
      <object type="TW3Label">
        <Caption>Frequency Multipliers</Caption>
        <Width>176</Width>
        <Top>64</Top>
        <Left>128</Left>
        <Height>32</Height>
        <Name>W3Label4</Name>
      </object>
      <object type="TW3Button">
        <Caption>View Waves</Caption>
        <Width>128</Width>
        <Top>36</Top>
        <Left>599</Left>
        <Height>32</Height>
        <Name>btnView</Name>
        <OnClick>btnViewClick</OnClick>
      </object>
      <object type="TW3ListBox">
        <Width>40</Width>
        <Top>29</Top>
        <Left>40</Left>
        <Height>56</Height>
        <Name>W3ListBox1</Name>
      </object>
      <object type="TW3Label">
        <Caption>(Sum is white)</Caption>
        <Width>128</Width>
        <Top>68</Top>
        <Left>612</Left>
        <Height>32</Height>
        <Name>W3Label5</Name>
      </object>
    </object>
  </Form>
</SMART>

Programming - a skill for life!

by James Gunn: L6 Age ~16