The Twin Paradox

/*
**  TwinParadox.java
**  Sat May 08 18:01:45 EDT 1999
**
**  Generated by Data Representations' Simplicity for Java(tm)
*/

package TwinParadox;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import datarep.common.*;
import java.applet.*;
import ptolemy.plot.*;

public class TwinParadox extends Applet
	implements ActionListener, Runnable  {


	Label mVelLabel = new Label("Initial Velocity(c):",Label.RIGHT);
	TextField mVel = new TextField("0.99999999",10);
	Label mAccelLabel = new Label("Acceleration(c/s):",Label.RIGHT);
	TextField mAccel = new TextField("0.04",10);
	Button mGo = new Button("STOP!");
	Button mRebound = new Button( "Adjust bounds to fit graphs." );
	Panel mTopFlow1 = new Panel(new FlowLayout(FlowLayout.CENTER,5,5));
	Label mLTimeLabel = new Label("Local Elapsed Time (s):",Label.CENTER);
	Label mTTimeLabel = new Label("Traveler Elapsed Time (s):",Label.CENTER);
	Label mDETLabel = new Label("LET - TET (s):",Label.CENTER);
	Panel mTimeLabelGrid = new Panel(new GridLayout(1,3,5,5));
	TextField mLTime = new TextField("0.0",0);
	TextField mTTime = new TextField("0.0",0);
	TextField mDET = new TextField("0.0",0);
	Panel mTimeDisplayGrid = new Panel(new GridLayout(1,3,5,5));
	ProgressBar mMotionView = new ProgressBar(0,4500);
	Panel mTopGrid = new Panel(new GridLayout(4,1,5,5));
	Plot mGraph = new Plot();
	Panel mMainBorder = new Panel(new BorderLayout(5,5));
	
	// Custom declaration code starts here
	Thread mThread = null;
	public final static double C = 299792458;
	

	public TwinParadox() {
		mVel.setBackground(SystemColor.window);
		mVel.setForeground(SystemColor.windowText);
		mAccel.setBackground(SystemColor.window);
		mAccel.setForeground(SystemColor.windowText);
		mGo.addActionListener(this);
		mRebound.addActionListener(this);
		mTopFlow1.add(mVelLabel);
		mTopFlow1.add(mVel);
		mTopFlow1.add(mAccelLabel);
		mTopFlow1.add(mAccel);
		mTopFlow1.add(mGo);
		mTimeLabelGrid.add(mLTimeLabel);
		mTimeLabelGrid.add(mTTimeLabel);
		mTimeLabelGrid.add(mDETLabel);
		mLTime.setEditable(false);
		mLTime.setBackground(SystemColor.window);
		mLTime.setForeground(SystemColor.windowText);
		mTTime.setEditable(false);
		mTTime.setBackground(SystemColor.window);
		mTTime.setForeground(SystemColor.windowText);
		mDET.setEditable(false);
		mDET.setBackground(SystemColor.window);
		mDET.setForeground(SystemColor.windowText);
		mTimeDisplayGrid.add(mLTime);
		mTimeDisplayGrid.add(mTTime);
		mTimeDisplayGrid.add(mDET);
		mMotionView.setValue(0);
		mTopGrid.add(mTopFlow1);
		mTopGrid.add(mTimeLabelGrid);
		mTopGrid.add(mTimeDisplayGrid);
		mTopGrid.add(mMotionView);
		mGraph.setBackground(Color.white);
		mGraph.setForeground(Color.black);
		mMainBorder.add("North",mTopGrid);
		mMainBorder.add("Center",mGraph);
		mMainBorder.add("South",mRebound);
		add("Center",mMainBorder);
		
		// Custom constructor code starts here
	}

	public void actionPerformed(ActionEvent evt) {
		if ( evt.getSource() == mGo ) {
			if( mThread == null )
			{
				start();
			}
			else
			{
				stop();
			}
		}
		if ( evt.getSource() == mRebound ) {
			mGraph.fillPlot();
		}
	}

	public void run()
	{
		double v = C* new Double( mVel.getText() ).doubleValue();
		double a = C* new Double( mAccel.getText() ).doubleValue();
		
		double x = 0; // distance from traveler to base from local point of view
		double let = 0; // local elapsed time
		double xp = 0; // distance from traveler to base from traveler point of view
		double tet = 0; // traveler elapsed time
		long startTime;
		double dt = 0.1; // 6 frames per second
		double dv = a*dt; 
		double dx; //change in distance from local pov
		double dxp; //change in distance from traveler pov
		double scale = v*v/2/a/4400;
		
		mGraph.clear( true );
		mGraph.setXRange(0,50);
		mGraph.setYRange(0,50);
		mGraph.addLegend( 0, "LET vs. TET" );
		mGraph.addLegend( 1, "LET vs. LET-TET" );
		mGraph.addLegend( 2, "X/C vs. LET" );
		mGraph.addLegend( 3, "X'/C vs. TET" );
		mGraph.addPoint( 0, let, tet, false );
		mGraph.addPoint( 1, let, let-tet, false );
		mGraph.addPoint( 2, x/C, let, false );
		mGraph.addPoint( 3, xp/C, tet, false );
		mGraph.repaint();
		
		do
		{
			//remember when we started so we can sleep the right amount of time
			startTime = System.currentTimeMillis();
			
			mMotionView.setValue( (int)(x/scale) );
			mLTime.setText( "" + let );
			mTTime.setText( "" + tet );
			mDET.setText( "" + (let-tet) );
			mGraph.addPoint( 0, let, tet, true );
			mGraph.addPoint( 1, let, let-tet, true );
			mGraph.addPoint( 2, x/C, let, true );
			mGraph.addPoint( 3, xp/C, tet, true );
			
			dx = v*dt;
			x = x + dx;
			v = v - dv;
			let = let + dt;
			tet = tet + Math.sqrt( C*C*dt*dt - dx*dx )/C;
			xp = xp + dx*Math.sqrt( 1 - (v/C)*(v/C) );
		
			//Ensure all components have updated
			getToolkit().sync();
			
			//sleep the right amount of time
			try{ mThread.sleep( (long)(dt*1000-(System.currentTimeMillis()-startTime)) ); }
			catch(Exception e){}
			
			}while( x >= 0 );
		stop();
	}
	
	public void start() {
		if( mThread == null )
		{
			mThread = new Thread( this );
		}
		mThread.start();
		mGo.setLabel( "STOP!" );
	}
	
	public void stop() {
		if( mThread != null )
		{
			mThread.stop();
		}
		mThread = null;
		mGo.setLabel( "GO!" );
	}
	
	public void destroy() {
		stop();
	}
	


}
Introduction Java Demonstration Explanation