import java.awt.*;
import java.applet.*;
import java.lang.Math;

/**
 * An interactive test of the Graphics.drawArc and Graphics.fillArc
 * routines. Can be run either as a standalone application by
 * typing "java Spirograph" or as an applet in the AppletViewer.
 */

public class Spirograph extends Applet {
	SpiroControls controls;

	public void init() {
		setLayout(new BorderLayout());
		SpiroCanvas c = new SpiroCanvas();
		
		add("Center", c);
 		add("South", controls = new SpiroControls(c));
    }

	public void start() {
		controls.enable();
	}

	public void stop() {
		controls.disable();
	}

	public boolean handleEvent(Event e) {
		if (e.id == Event.WINDOW_DESTROY) {
			System.exit(0);
		}
		return false;
	}

	public static void main(String args[]) {
		Frame f = new Frame("Spirograph");
		Spirograph spiro = new Spirograph();
	
		spiro.init();
		spiro.start();

		f.add("Center", spiro);
		f.resize(300, 300);
		f.show();
    }
}

class SpiroCanvas extends Canvas {
	double		outside = 120;
	double		inside = 40;
	double		penpos = 0.9;
	Font		font;
    
	public void paint(Graphics g) {
		Rectangle r = bounds();
		double itheta = 0;
		double otheta = 0;
		double ratio = (1.0*outside)/inside;
		double orad = Math.min(r.height/2.0, r.width/2.0);
		double irad = orad/ratio;
		int centerx = r.width/2;
		int centery = r.height/2;
		int oldx = -100;
		int oldy = -100;
		int startx = 0, starty = 0;
		int x,y;
		boolean canQuit = false;

		double delta=0.05;

        g.setColor(Color.black);
        for (otheta=0.0; otheta < 1000.0; otheta+=0.05 ) {
                itheta = -otheta*ratio;
                x = centerx+(int)(Math.cos(otheta)*(orad-irad) + Math.cos(otheta+itheta)*irad*penpos);
                y = centery+(int)(Math.sin(otheta)*(orad-irad) + Math.sin(otheta+itheta)*irad*penpos);

				if (oldx==-100) {
					oldx = x; oldy = y;
					startx = x; starty = y;
				}
				else if (x==startx && y==starty)
				{
					if (canQuit) break;
				}
				else canQuit = true;
				
                g.drawLine(oldx, oldy, x, y);
                oldx = x; oldy = y;
        }
	}

	public void redraw(double outside, double inside, double penpos) {
		this.outside = outside;
		this.inside = inside;
		this.penpos = penpos;
		repaint();
	}
}

class SpiroControls extends Panel {
    TextField s;
    TextField e;
	TextField r;
    SpiroCanvas canvas;

    public SpiroControls(SpiroCanvas canvas) {
		this.canvas = canvas;

		add(s = new TextField("120", 5));
        add(e = new TextField("40", 5));
        add(r = new TextField("0.9", 5));
		add(new Button("Draw"));
	}

	public boolean action(Event ev, Object arg) {
		if (ev.target instanceof Button) {
			Double d1 = new Double(s.getText().trim());
			Double d2 = new Double(e.getText().trim());
			Double d3 = new Double(r.getText().trim());
			String label = (String)arg;

			canvas.redraw(d1.doubleValue(), d2.doubleValue(), d3.doubleValue());
			return true;
		}
		return false;
	}
}

	

