[ Prev | Index | Next ]
Japanese English
Now Loading...
Download
Please download on PC (not smartphone) and extract the ZIP file. Then double-click VCSSL.bat (batch file) to execute for Microsoft® Windows®, or execute VCSSL.jar (JAR file) on the command line for Linux® and other OSes.
For details, see How to Use.
You are free to use and modify this program and material, even for educational or commercial use. » Details

Wave Interference Animation (Two Sine Waves on a Line)

This is a simple simulator developed in VCSSL to visualize the interference between sine waves traveling along a one-dimensional line.

- Table of Contents -

In the previous article, we focused on the animation of a single sine wave. This article continues from there. If you're not yet familiar with what a sine wave is, please refer to that article first. Here, we'll superimpose two sine waves and animate how they interfere with each other.

[ Related Article ]

How to Use

Download and Extract

At first, click the "Download" button at the above of the title of this page by your PC (not smartphone). A ZIP file will be downloaded.

If you are using Windows, right-click the ZIP file and choose "Properties" from the menu, and enable "Unblock" checkbox at the right-bottom (in the line of "Security") of the properties-window. Otherwise, when you extract the ZIP file or when you execute the software, security warning messages may pop up and the extraction/execution may fail.

Then, please extract the ZIP file. On general environment (Windows®, major Linux distributions, etc.), you can extract the ZIP file by selecting "Extract All" and so on from right-clicking menu.

» If the extraction of the downloaded ZIP file is stopped with security warning messages...

Execute this Program

Next, open the extracted folder and execute this VCSSL program.

For Windows

Double-click the following batch file to execute:

VCSSL__Double_Click_This_to_Execute.bat

For Linux, etc.

Execute "VCSSL.jar" on the command-line terminal as follows:

cd <extracted_folder>
java -jar VCSSL.jar

» If the error message about non-availability of "java" command is output...

After Launching the Program

When the program starts, you'll be asked whether to input numerical values for the wave parameters. If you don't have a specific need like "setting the wavelength to exactly this value," it's fine to just skip this by choosing "No."

Then, two windows will appear: a graph window and a parameter setting window.

Graph Window and Setting Window

In the graph window, the sine waves are animated.

The red and blue curves represent the two individual waves (Wave A and Wave B) to be superimposed. The green curve represents the resulting composite wave formed by their interference. In the parameter setting window, you can adjust values such as the amplitude, wavelength, and period independently for each wave using sliders.

Closing either window will terminate the program.

Note for users who have difficulty distinguishing red and green:

If it's hard to tell apart Wave A (red) and the composite wave (green), you can change their colors freely by selecting Edit > Set Color from the menu at the top of the graph window.

In the color settings window, Series No.1 corresponds to Wave A, No.2 to Wave B, and No.3 to the composite wave. For example, if you set No.3 to "BLACK", the composite wave will be drawn in black instead of green.

Color Settings Result

Concept Overview

When multiple waves are superimposed, the resulting wave often takes on a shape (and motion) that is quite different from the original waves. This phenomenon is called interference.

For example, sine waves follow the shape of the sin function. When two sine waves with slightly different wavelengths are superimposed, a distinctive pattern appears: areas of large amplitude and small amplitude (even close to zero) alternate along the x-axis. The result looks like a distorted sine wave, as shown by the green curve below:

Figure of Different Wavelength
( Wave A: A=1.0, =0.35, T=1.0     Wave B: A=1.0, =0.4, T=1.0 )

If the periods are different instead, the amplitude changes over time even at the same position along the x-axis. This is known as a beat phenomenon.

Figure of Different Period
( Wave A: A=1.0, =0.4, T=2.0     Wave B: A=1.0, =0.4, T=1.0 )

When both wavelength and period differ, you can observe the unique pattern along the x-axis shifting over time.

Figure of Different Wavelength and Period
( Wave A: A=1.0, =0.35, T=1.0     Wave B: A=1.0, =0.4, T=0.5 )

What's especially interesting is that the pattern of amplitude variation (the envelope) and the distorted sine waves within it generally move in different directions and at different speeds. The speed of the envelope is called the group velocity, while the speed of the inner waves is called the phase velocity.

The phase velocity also applies to single sine waves -- it's simply the speed of the wave itself. For composite waves made from two similar sine waves, the phase velocity is almost the same as that of the originals.

In contrast, the group velocity depends on the ratio of the differences in wavelength and period (or, equivalently, the difference in wave number and angular frequency). If you superimpose a continuous spectrum of many waves with varying wavelengths and periods, the ratio becomes a derivative instead of a simple difference.

Code

This program is written in VCSSL.

Here, we'll briefly explain the contents of the code. Since VCSSL uses a simple C-like syntax, it should be relatively easy to read for anyone who has experience with C or similar languages.

If you'd like to customize this program -- such as changing the graph range or making other modifications -- you can open the source file SineWave.vcssl in any text editor and edit it directly. Since VCSSL is a scripting language, no compiler or external software is needed: simply modify the code and run it.

Full Code

Let's first take a look at the entire code:


coding UTF-8;        // Specify the character encoding (to prevent garbled text)
import Math;         // Import library for using mathematical functions
import GUI;          // Import library for building GUI windows
import tool.Graph2D; // Import library for 2D graph plotting


// Variables for storing wave parameters
double amplitudeA = 1.0;   // Amplitude (A) of Wave A
double amplitudeB = 1.0;   // Amplitude (A) of Wave B
double wavelengthA = 0.35; // Wavelength () of Wave A
double wavelengthB = 0.4;  // Wavelength () of Wave B
double periodA = 1.0;      // Period (T) of Wave A
double periodB = 0.5;      // Period (T) of Wave B

// Configuration variables for graph range, number of points, time steps, etc.
const int N = 1024;          // Number of points on the graph (higher for smoother curves)
const double X_MIN = 0.0;    // Minimum value of the X-axis
const double X_MAX = 4.0;    // Maximum value of the X-axis
const double Y_MIN = -2.0;   // Minimum value of the Y-axis
const double Y_MAX = 2.0;    // Maximum value of the Y-axis
const double DT = 0.05;      // Time increment per loop (when speed = 1.0)
const double DX = (X_MAX - X_MIN) / N; // X-axis spacing between points

// Arrays to store coordinate data for passing wave data to the graph
double waveX[ 3 ][ N ];  // X-coordinates (3 series: Wave A, Wave B, Composite Wave ~ number of points)
double waveY[ 3 ][ N ];  // Y-coordinates (3 series: Wave A, Wave B, Composite Wave ~ number of points)

// Variables for the GUI (parameter setting window)
int window;            // Stores the ID of the window
int periodSliderA;     // ID of the period slider for Wave A
int periodSliderB;     // ID of the period slider for Wave B
int wavelengthSliderA; // ID of the wavelength slider for Wave A
int wavelengthSliderB; // ID of the wavelength slider for Wave B
int amplitudeSliderA;  // ID of the amplitude slider for Wave A
int amplitudeSliderB;  // ID of the amplitude slider for Wave B
int speedSlider;       // ID of the animation speed slider
int infoLabelA;        // ID of the label displaying Wave A's parameters
int infoLabelB;        // ID of the label displaying Wave B's parameters
int timeLabel;         // ID of the label displaying the current time
int resetButton;       // ID of the button to reset time

// Other control-related variables
float speed = 0.5;         // Animation speed
int graph;                 // Stores the ID of the graph software instance
bool continuesLoop = true; // Controls whether the animation loop runs or stops
double t;                  // Time variable


// ======================================================================
// Main routine - this function runs automatically on startup
// ======================================================================

void main( ){
	
	// Ask the user whether to input initial wave parameters; input if needed
	inputParameters();
	
	// Launch the graph window
	createGraphWindow();
	
	// Build the GUI (parameter setting window)
	createSettingWindow();
	
	t = 0.0; // Initialize time to zero
	
	// Main animation loop
	while( continuesLoop ) {
		
		// Display the current time in the graph title
		string roundedTime = round(t, 1, HALF_UP);    // Round time to 1 decimal place
		setGraph2DTitle(graph, "t = " + roundedTime); // Set title as "t = [time]"
		
		// Calculate the coordinates of points for graph plotting
		for( int i=0; i<N; i++ ) {
			
			double x = X_MIN + i * DX; // X-coordinate of the i-th point
			
			// Wave A
			waveX[ 0 ][ i ] = x;
			waveY[ 0 ][ i ] = amplitudeA * sin( 2.0 * PI * ( t/periodA - x/wavelengthA ) );
			
			// Wave B
			waveX[ 1 ][ i ] = x;
			waveY[ 1 ][ i ] = amplitudeB * sin( 2.0 * PI * ( t/periodB - x/wavelengthB ) );
			
			// Composite Wave
			waveX[ 2 ][ i ] = x;
			waveY[ 2 ][ i ] = waveY[ 0 ][ i ] + waveY[ 1 ][ i ];
		}
		
		// Send the data to the graph
		setGraph2DData( graph, waveX, waveY );
		
		// Increment time (adjusted by animation speed)
		t += DT * speed;
		
		// Animation wait (sleep 30 ms)
		sleep( 30 );
	}
	
	exit(); // Exit when animation loop ends
}


// ======================================================================
// Function to prompt for initial wave parameters at startup
// ======================================================================

void inputParameters() {
	if ( confirm("Do you want to input wave parameters numerically?") ) {
		
		amplitudeA = input("Amplitude of Wave A=", amplitudeA);
		amplitudeB = input("Amplitude of Wave B=", amplitudeB);
		wavelengthA = input("Wavelength of Wave A=", wavelengthA);
		wavelengthB = input("Wavelength of Wave B=", wavelengthB);
		periodA = input("Period of Wave A=", periodA);
		periodB = input("Period of Wave B=", periodB);
		
	}
}


// ======================================================================
// Function to launch and configure the graph software
// ======================================================================

void createGraphWindow() {

	// Launch the 2D graph software
	graph = newGraph2D( 0, 0, 800, 600, "Graph Window" );
	
	// Disable auto-ranging and manually set the graph range
	setGraph2DAutoRange( graph, false, false );
	setGraph2DRange( graph, X_MIN, X_MAX, Y_MIN, Y_MAX );
	
	// Load configuration file (e.g., line widths, colors, etc.)
	setGraph2DConfigurationFile(graph, "./RinearnGraph2DSetting.ini");
	
	// Set plot options
	setGraph2DOption(graph, "WITH_POINTS", false);
	setGraph2DOption(graph, "WITH_LINES", true);
	
	// Set background color to white
	setGraph2DBackgroundColor( graph, 255, 255, 255, 255 );
	
	// Set axis labels and graph title
	setGraph2DLabel( graph, "x", "Two Sine Waves (Red, Blue) and Composite Wave (Green)" );
}


// ======================================================================
// Function to build the parameter setting window
// ======================================================================

void createSettingWindow() {

	// Create the window
	window = newWindow( 0, 600, 800, 230, "Setting Window" );
	
	// Create and place the label that displays current time
	timeLabel = newTextLabel( 10, 10, 200, 20, "" );
	mountComponent( timeLabel, window );
	
	// Create and place labels to the left of sliders for amplitude, period, and wavelength
	int amplitudeLabel = newTextLabel( 10, 40, 135, 15, "A: Amplitude (0-1)" );
	mountComponent( amplitudeLabel, window );
	int omegaLabel = newTextLabel( 10, 60, 135, 15, "T: Period (0.2-5)" );
	mountComponent( omegaLabel, window );
	int lambdaLabel = newTextLabel( 10, 80, 135, 15, ": Wavelength (0.1-4)" );
	mountComponent( lambdaLabel, window );
	
	// Create and place sliders for amplitude (range: 0.0-1.0)
	amplitudeSliderA = newHorizontalSlider( 150, 40, 300, 20, amplitudeA, 0.0, 1.0 );
	amplitudeSliderB = newHorizontalSlider( 450, 40, 300, 20, amplitudeB, 0.0, 1.0 );
	mountComponent( amplitudeSliderA, window );
	mountComponent( amplitudeSliderB, window );
	
	// Create and place sliders for period (range: 0.2-5.0)
	periodSliderA = newHorizontalSlider( 150, 60, 300, 20, periodA, 0.2, 5.0 );
	periodSliderB = newHorizontalSlider( 450, 60, 300, 20, periodB, 0.2, 5.0 );
	mountComponent( periodSliderA, window );
	mountComponent( periodSliderB, window );
	
	// Create and place sliders for wavelength (range: 0.1-4.0)
	wavelengthSliderA = newHorizontalSlider( 150, 80, 300, 20, wavelengthA, 0.1, 4.0 );
	wavelengthSliderB = newHorizontalSlider( 450, 80, 300, 20, wavelengthB, 0.1, 4.0 );
	mountComponent( wavelengthSliderA, window );
	mountComponent( wavelengthSliderB, window );
	
	// Create and place labels to display slider values
	infoLabelA = newTextLabel( 155, 100, 300, 20, "" );	
	infoLabelB = newTextLabel( 455, 100, 300, 20, "" );	
	mountComponent( infoLabelA, window );
	mountComponent( infoLabelB, window );
	updateInfoLabel();
	
	// Create and place labels for the columns of Wave A and Wave B
	int columnLabelA = newTextLabel(280, 15, 200, 20, "Wave A");
	int columnLabelB = newTextLabel(580, 15, 200, 20, "Wave B");
	mountComponent( columnLabelA, window );
	mountComponent( columnLabelB, window );
	
	// Create and place label and slider for adjusting animation speed
	int speedLabel = newTextLabel( 10, 140, 140, 15, "Animation Speed" );
	mountComponent( speedLabel, window );
	speedSlider = newHorizontalSlider( 150, 140, 400, 20, speed, 0.0, 1.0 );
	mountComponent( speedSlider, window );
	
	// Create and place the button to reset the time
	resetButton = newButton(600, 125, 150, 40, "Reset Time");
	mountComponent( resetButton, window );
	
	// Refresh the window display after mounting components
	paintComponent( window );
}


// ======================================================================
// Function to update the labels that display slider values
// ======================================================================

void updateInfoLabel() {
	string infoTextA
		= "( A="
		+ round(amplitudeA, 3, HALF_UP) // Round amplitude to 3 decimal places
		+ ", ="
		+ round(wavelengthA, 3, HALF_UP) // Round wavelength to 3 decimal places
		+ ", T="
		+ round(periodA, 3, HALF_UP) // Round period to 3 decimal places
		+ ")";
	
	string infoTextB
		= "( A="
		+ round(amplitudeB, 3, HALF_UP) // Round amplitude to 3 decimal places
		+ ", ="
		+ round(wavelengthB, 3, HALF_UP) // Round wavelength to 3 decimal places
		+ ", T="
		+ round(periodB, 3, HALF_UP) // Round period to 3 decimal places
		+ ")";
	
	setComponentString(infoLabelA, infoTextA);
	setComponentString(infoLabelB, infoTextB);
	paintComponent(infoLabelA);
	paintComponent(infoLabelB);
	paintComponent(window);
}


// ======================================================================
// Event handler called when a slider is moved
// ======================================================================

void onSliderMove(int id, float value) {
	
	// Set the value to the corresponding global variable
	
	if(id == amplitudeSliderA) {
		amplitudeA = value;
	}
	
	if(id == amplitudeSliderB) {
		amplitudeB = value;
	}
	
	if(id == periodSliderA) {
		periodA = value;
	}
	
	if(id == periodSliderB) {
		periodB = value;
	}
	
	if(id == wavelengthSliderA) {
		wavelengthA = value;
	}
	
	if(id == wavelengthSliderB) {
		wavelengthB = value;
	}
	
	if (id == speedSlider) {
		speed = value;
	}
	
	updateInfoLabel();
}


// ======================================================================
// Event handler called when a button is clicked
// ======================================================================

void onButtonClick(int id) {
	
	// If the reset button was clicked, reset the time variable
	if (id == resetButton) {
		t = 0.0;
	}
}


// ======================================================================
// Event handler called when a window is closed
// ======================================================================

void onWindowClose(int id) {
	
	// Exit the animation loop to end the program
	continuesLoop = false;
}


// ======================================================================
// Event handler called when the graph window is closed
// ======================================================================

void onGraph2DClose(int id) {
	
	// Exit the animation loop to end the program
	continuesLoop = false;
}
InterferingSineWave_SJIS.vcssl

That's it. It's a short program, a bit over 300 lines. Most of the logic is already explained in the inline comments within the code itself, but in this section, we'll walk through the main parts in more detail.

This program is largely based on the code from the previous article, Sine Wave Animation. The main difference is that now we're working with two sine waves instead of one, and the code has been slightly extended to accommodate that.

So if you're new to the basic structure, we recommend reviewing the earlier code first.

Below, we'll focus on the parts that have changed since the previous version.

Variable Declarations

At the beginning of the program, variables are declared-just like in the previous version. The key difference is that now we have two waves, so parameters and slider controls are prepared separately for Wave A and Wave B.

One notable change is the arrays used to store coordinate data for plotting. Previously, we only needed 1D arrays, but now we use 2D arrays:


// Arrays to store coordinate data for passing wave data to the graph
double waveX[ 3 ][ N ];  // X-coordinates (3 series: Wave A, Wave B, Composite Wave ~ number of points)
double waveY[ 3 ][ N ];  // Y-coordinates (3 series: Wave A, Wave B, Composite Wave ~ number of points)
array.txt

This is because we now need to pass multiple data series to the graph. The first dimension (the leftmost one) corresponds to the different wave series: Wave A, Wave B, and the composite wave, totaling three.

The second dimension is for the individual data points within each wave, same as before. Each series contains N points, which are connected by lines in the graph.

Assigning Wave Data and Plotting in the main Function

Now let's look at the part inside the animation loop in the main() function where wave data is calculated and passed to the graph:


// Calculate the coordinates of points for graph plotting
for( int i=0; i<N; i++ ) {

	double x = X_MIN + i * DX; // X-coordinate of the i-th point

	// Wave A
	waveX[ 0 ][ i ] = x;
	waveY[ 0 ][ i ] = amplitudeA * sin( 2.0 * PI * ( t/periodA - x/wavelengthA ) );

	// Wave B
	waveX[ 1 ][ i ] = x;
	waveY[ 1 ][ i ] = amplitudeB * sin( 2.0 * PI * ( t/periodB - x/wavelengthB ) );

	// Composite Wave
	waveX[ 2 ][ i ] = x;
	waveY[ 2 ][ i ] = waveY[ 0 ][ i ] + waveY[ 1 ][ i ];
}

// Send the data to the graph
setGraph2DData( graph, waveX, waveY );
trans.txt

This block is inside the animation loop, so you can think of it as drawing one frame of the graph at a specific time "t". By incrementally increasing t and repeatedly running this loop -- like a flipbook -- the graph appears animated.

For Wave A and Wave B, the logic is essentially the same as in the previous program: We compute the Y-value of a sine wave at each small step along the X-axis using the formula:

\[ y = A \sin 2 \pi \bigg( \frac{t}{T} - \frac{x}{\lambda} \bigg) \]

Then we store those X and Y values into arrays. The graphing software connects the dots automatically to form the wave shapes.

The next part is the composite wave, which we calculate by simply adding the Y-values of Wave A and Wave B at each point. It may seem almost too simple, but for typical physical waves, this approach works accurately thanks to the principle of superposition, which holds well in everyday scenarios.

In other words, this program assumes a perfectly ideal case where the principle of superposition holds precisely.

Note: Of course, there are situations where superposition doesn't hold this simply. In such cases, you can't just add the wave values directly. Instead, you'd typically start with a predefined composite wave and use numerical methods to solve the time-evolution differential equations to simulate how it evolves over time.

Other Parts

The rest of the code is a straightforward extension of the previous version. Sliders and controls are added for the two separate waves, but no major structural changes were made.

That's all for the code explanation!

License

This VCSSL/Vnano code (files with the ".vcssl" or ".vnano" extensions) is released under the CC0 license, effectively placing it in the public domain. If any sample code in C, C++, or Java is included in this article, it is also released under the same terms. You are free to use, modify, or repurpose it as you wish.

* The distribution folder also includes the VCSSL runtime environment, so you can run the program immediately after downloading. The license for the runtime is included in the gLicenseh folder.
(In short, it can be used freely for both commercial and non-commercial purposes, but the developers take no responsibility for any consequences arising from its use.) For details on the files and licenses included in the distribution folder, please refer to "ReadMe.txt".

* The Vnano runtime environment is also available as open-source, so you can embed it in other software if needed. For more information, see here.


Japanese English
[ Prev | Index | Next ]
Wave Interference Animation (Two Circular Waves on a Plane)

Interactive simulator for visualizing wave interference between two circular waves on a plane.
Circular Wave Animation

Interactive simulator for animating circular waves on a plane with adjustable parameters.
Wave Interference Animation (Two Sine Waves on a Line)

Interactive simulation of wave interference between two 1D sine waves.
Sine Wave Animation

Interactive simulator for animating sine waves with adjustable parameters.
Vnano | Solve The Lorenz Equations Numerically

Solve the Lorenz equations, and output data to plot the solution curve (well-known as the "Lorenz Attractor") on a 3D graph.
Index
[ Prev | Index | Next ]
Wave Interference Animation (Two Circular Waves on a Plane)

Interactive simulator for visualizing wave interference between two circular waves on a plane.
Circular Wave Animation

Interactive simulator for animating circular waves on a plane with adjustable parameters.
Wave Interference Animation (Two Sine Waves on a Line)

Interactive simulation of wave interference between two 1D sine waves.
Sine Wave Animation

Interactive simulator for animating sine waves with adjustable parameters.
Vnano | Solve The Lorenz Equations Numerically

Solve the Lorenz equations, and output data to plot the solution curve (well-known as the "Lorenz Attractor") on a 3D graph.
News From RINEARN
* VCSSL is developed by RINEARN.

English Documentation for Our Software and VCSSL Is Now Nearly Complete
2025-06-30 - We're happy to announce that the large-scale expansion of our English documentation with the support of AI — a project that began two years ago — has now reached its initial target milestone.

VCSSL 3.4.52 Released: Enhanced Integration with External Programs and More
2025-05-25 - This update introduces enhancements to the external program integration features (e.g., for running C-language executables). Several other improvements and fixes are also included. Details inside.

Released: Latest Version of VCSSL with Fixes for Behavioral Changes on Java 24
2025-04-22 - VCSSL 3.4.50 released with a fix for a subtle behavioral change in absolute path resolution on network drives, introduced in Java 24. Details inside.

Released the Latest Versions of RINEARN Graph and VCSSL - Now Supporting Customizable Tick Positions and Labels!
2024-11-24 - Starting with this update, a new "MANUAL" tick mode is now supported, allowing users to freely specify the positions and labels of ticks on the graph. We'll explain the details and how to use it.

Released Exevalator 2.2: Now Compatible with TypeScript and Usable in Web Browsers
2024-10-22 - The open-source expression evaluation library, Exevalator, has been updated to version 2.2. It now supports TypeScript and can be used for evaluating expressions directly in web browsers. Explains the details.

Behind the Scenes of Creating an Assistant AI (Part 1: Fundamental Knowledge)
2024-10-07 - The first part of a series on how to create an Assistant AI. In this article, we introduce the essential knowledge you need to grasp before building an Assistant AI. What exactly is an LLM-based AI? What is RAG? And more.

Launching an Assistant AI to Support Software Usage!
2024-09-20 - We've launched an Assistant AI that answers questions about how to use RINEARN software and helps with certain tasks. Anyone with a ChatGPT account can use it for free. We'll explain how to use it.

Software Updates: Command Expansion in RINEARN Graph, and English Support in VCSSL
2024-02-05 - We updated our apps. This updates include "Enhancing the Command-Line Features of RINEARN Graph" and "Adding English Support to VCSSL." Dives into each of them!