/* Viewing Sources */


/*
Nhan Le
This applet graphically demonstrates some permutations of random parametric equations.

<applet code="ParametricLab" width="400" height="400"></applet>
*/


import java.awt.*;
import java.applet.*;
import java.util.*;

public class ParametricLab extends Applet implements Runnable{
	/*
	The below inner classes each possess unique x and y parametric equations
	*/
	interface Function{
		public double f(double t);
		public String getName();
	}
	class Equation0 implements Function{
		private double mag;
		private double n;
		public Equation0(double mag, double n){
			this.mag = mag;
			this.n = n;
		}
		public double f(double t){
			return (double)(mag*Math.cos(n*t));
		}
		public String getName(){
			return mag+"cos("+n+"t)";
		}
	}
	class Equation1 implements Function{
		private double mag;
		private double n;		
		public Equation1(double mag, double n){
			this.mag = mag;
			this.n = n;			
		}
		public double f(double t){
			return (double)(mag*Math.sin(n*t));
		}
		public String getName(){
			return mag+"sin("+n+"t)";
		}
	}
	class Equation2 implements Function{
		private double mag;
		private double n;
		public Equation2(double mag, double n){
			this.mag = mag;
			this.n = n;			
		}
		public double f(double t){
			return (double)(mag*Math.tan(n*t));
		}
		public String getName(){
			return mag+"tan("+n+"t)";
		}
	}
	class Equation3 implements Function{
		private double mag;
		private double n;
		public Equation3(double mag, double n){
			this.mag = mag;
			this.n = n;			
		}
		public double f(double t){
			return (double)(mag*(1.0/Math.sin(n*t)));
		}
		public String getName(){
			return mag+"csc("+n+"t)";
		}
	}
	class Equation4 implements Function{
		private double mag;
		private double n;
		public Equation4(double mag, double n){
			this.mag = mag;
			this.n = n;			
		}
		public double f(double t){
			return (double)(mag*(1.0/Math.cos(n*t)));
		}
		public String getName(){
			return mag+"sec("+n+"t)";
		}
	}
	class Equation5 implements Function{
		private double mag;
		private double n;
		public Equation5(double mag, double n){
			this.mag = mag;
			this.n = n;			
		}
		public double f(double t){
			return (double)(mag*(1.0/Math.tan(n*t)));
		}
		public String getName(){
			return mag+"cot("+n+"t)";
		}
	}
	class Equation6 implements Function{
		private double mag;
		private double n;
		public Equation6(double mag, double n){
			this.mag = mag;
			this.n = n;			
		}
		public double f(double t){
			return (double)(mag*(Math.atan(n*t)));
		}
		public String getName(){
			return mag+"arctan("+n+"t)";
		}
	}
	class Equation7 implements Function{
		private double mag1;
		private double n1;
		private double mag2;
		private double n2;
		public Equation7(double mag1, double n1, double mag2, double n2){
			this.mag1 = mag1;
			this.n1 = n1;			
			this.mag2 = mag2;
			this.n2 = n2;			
		}
		public double f(double t){
			return (double)(mag1*Math.cos(n1*t)+mag2*Math.sin(n2*t));
		}
		public String getName(){
			return mag1+"cos("+n1+"t) + "+mag2+"sin("+n2+"t)";
		}
	}
	class Equation8 implements Function{
		private double mag1;
		private double n1;
		private double mag2;
		private double n2;
		public Equation8(double mag1, double n1, double mag2, double n2){
			this.mag1 = mag1;
			this.n1 = n1;			
			this.mag2 = mag2;
			this.n2 = n2;			
		}
		public double f(double t){
			return (double)(mag1*(((Math.exp(n1*t))-(Math.exp(-n1*t)))/((Math.exp(n1*t))+(Math.exp(-n1*t))))+mag2*Math.sin(n2*t));
		}
		public String getName(){
			return mag1+"tanh("+n1+"t) + "+mag2+"sin("+n2+"t)";
		}
	}

	private volatile Thread self = null;
	private Function x;
	private Function y;
	private	Random r = new Random();
	public final double width = 400.0;
	public final double height = 400.0;
	public final double xscale = 24.0;
	public final double yscale = 24.0;
	private int step = 0;
	public void init(){
		self = new Thread(this);
		self.start();
	}
	public void run(){
		Thread current = Thread.currentThread();
		try{
			while(current==self){
				rechooseFunctions();
				repaint();
				Thread.sleep(3000);				
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	private void rechooseFunctions(){
		//randomly select functions
		Function[] list = {
			new Equation0(rand(8,3),rand(12,3)), 
			new Equation1(rand(8,3),rand(12,3)), 
			new Equation2(rand(8,3),rand(12,3)),
			new Equation3(rand(8,3),rand(12,3)), 
			new Equation4(rand(8,3),rand(12,3)), 
			new Equation5(rand(8,3),rand(12,3)),
			new Equation6(rand(8,3),rand(12,3)), 
			new Equation7(rand(8,3),rand(12,3),rand(8,3),rand(12,3)), 
			new Equation8(rand(8,3),rand(12,3),rand(8,3),rand(12,3))
		};
		int randomA = Math.abs(r.nextInt()%list.length);
		int randomB = Math.abs(r.nextInt()%list.length);
		while(!(randomA!=randomB))//make sure the functions aren't the same because the parametric would be boring if it was
			randomB = Math.abs(r.nextInt()%list.length);
		x = list[randomA];
		y = list[randomB];
	}
	private double rand(int max, int min){//maybe update
		return Math.abs(r.nextInt()%(max-min))+min;
	}
	public void paint(Graphics g){
		g.translate((int)width/2,(int)height/2);
		double xzoomfactor = (width/xscale);
		double yzoomfactor = (height/yscale);

		//draw grid<
			//update color<
				setBackground(Color.black);
				switch(step%4){
				case 0: g.setColor(new Color(100,0,0)); break;
				case 1: g.setColor(new Color(0,0,100)); break;
				case 2: g.setColor(new Color(100,100,0)); break;
				case 3:	g.setColor(new Color(0,100,0)); break;	
				}
			//>
			for(double x=-xscale/2; x<=xscale/2; x++){
				g.drawLine(
					(int)(xzoomfactor*x),	(int)(-height/2),
					(int)(xzoomfactor*x),	(int)(height/2)
				);
			}
			for(double y=-yscale/2; y<=xscale/2; y++){
				g.drawLine(
					(int)(-width/2),	(int)(yzoomfactor*y),
					(int)(width/2),		(int)(yzoomfactor*y)	
				);
			}

		//>
		

		//draw parametric functions<
			//update color<
				setBackground(Color.black);
				switch(step++%4){
				case 0: g.setColor(Color.red); break;
				case 1: g.setColor(Color.blue); break;
				case 2: g.setColor(Color.yellow); break;
				case 3:	g.setColor(Color.green); break;	
				}
			//>

			double t_initial=-xscale/2.0;
			double t_final=xscale/2.0;
			for(double t=t_initial; t<=t_final; t+=0.2){
				g.drawLine(
					(int)(xzoomfactor*x.f(t)),		(int)(yzoomfactor*y.f(t)),
					(int)(xzoomfactor*x.f(t+1)),	(int)(yzoomfactor*y.f(t+1))
				);
			}
		//>
		
		//label functions<
			g.setColor(Color.white);
			g.drawString("f(t) = { x="+x.getName()+", y="+y.getName()+" }",(int)(-width/2.0)+20,(int)(height/2.0)-20);
			System.out.println("f(t) = { x="+x.getName()+", y="+y.getName()+" }");
		//>
	}
	public void start(){
		if(self==null){
			self = new Thread(this);
			self.start();
		}			
	}
	public void stop(){
		self = null;
	}
}

/* sources by Nhan Le */
/* [email protected] */
/* [email protected] */
/* [email protected] */
/* if you find the sources useful or if you want to make any modifications, just email me */
/* html generated using GNU source-highlight 1.8 =-) */