/**
 * trace une astroïde
 * 26/09/98 - double-buffering et adapté jdk 1.2 le 02/04/99
 *
 * @ author Jean-Paul Quelen
 * modifié le 18/12/17 et le 15/09/22
 */

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class astro extends Panel implements Runnable, ActionListener {
	static final long serialVersionUID = 220915L;
	int xyMax, xy0, r, rx2, rx3, rx4, rx8, xy0mrx4, DT;
	int xM, yM, xM1, yM1, xC, yC, xC1, yC1, xy0mr, xy0pr, xy0m2;
	double t, dt, adt, z;
	static Thread trace;
	boolean btrace = true;
	TextField TFadt, TFDT;
	Button recule, avance, stop, tr;
	static Image img;
	static Graphics g;
	int gw, gh;
	int epPoint = 5;
 
	public astro() {
		setFont (new Font (Font.SANS_SERIF, Font.PLAIN, 10));
		setBackground (Color.WHITE);
		t = 0.0;
		dt = adt = 0.05;
		DT = 50;
		add (recule = new Button ("<<"));
		recule.addActionListener (this);
		add (avance = new Button (">>"));
		avance.addActionListener (this);
		add (stop = new Button ("Stop"));
		stop.addActionListener (this);
		add (tr = new Button ("Trace"));
		tr.addActionListener (this);
		add (new Label ("dt ="));
		TFadt = new TextField ("0.05", 10);
		add (TFadt);
		TFDT = new TextField ("50", 10);
		add (TFDT);
		add (new Label ("ms"));
		trace = new Thread (this);
		trace.start();
	}

	public void run() {
		Thread th = Thread.currentThread ();
		while (th == trace) {
			repaint ();
			try {
				Thread.sleep (DT);
			}
			catch (InterruptedException e) {}
		}
	}

	public void update (Graphics g1) {
		paint (g1);
	}

	public void paint (Graphics g1) {
		if (img == null || gw != getSize().width || gh != getSize().height) {
			gw = getSize().width;
			gh = getSize().height;
			img = createImage (gw, gh);
			g = img.getGraphics();

			xyMax = gh; xy0 = gh;
			xyMax = (xyMax > xy0 ? xy0 : xyMax);
			xy0 = xyMax / 2;
			r = xyMax / 8; rx2 = xyMax / 4; rx3 = r + rx2;rx4 = xyMax / 2;
			rx8 = xyMax; xy0mrx4 = xy0 - rx4;
			xy0mr = xy0 - r;
			xy0pr = xy0 + r;
			xy0m2 = xy0 - 2;
			xC = rx3; yC = 0; xM = rx4; yM = 0;
			g.setColor (Color.WHITE);
			g.fillRect (0, 0, gw, gh);
		}

		g.setColor (Color.WHITE);
		g.drawOval (xy0mr + xC1, xy0mr + yC1, rx2, rx2);
		if (!btrace)
			g.fillOval (xM1 + xy0m2, yM1 + xy0m2, epPoint, epPoint);

		g.setColor (Color.RED);
		g.drawLine (0, xy0, xyMax, xy0);
		g.drawLine (xy0, 0, xy0, xyMax);

		g.setColor (Color.BLACK);
		g.drawOval (xy0mrx4, xy0mrx4, rx8, rx8);
		g.drawOval (xy0mr + xC, xy0mr + yC, rx2, rx2);

		g.setColor (Color.BLUE);
		g.fillOval (xM + xy0m2, yM + xy0m2, epPoint, epPoint);

		g1.drawImage (img, 0, 0, this);

		xC1 = xC;
		yC1 = yC;
		xM1 = xM;
		yM1 = yM;
		t = t - dt;
		xC = (int) ((double) rx3 * Math.cos (t)); 
		yC = (int) ((double) rx3 * Math.sin (t));
		z =	Math.cos (t);
		xM = (int) ((double) rx4 * z * z * z) ;
		z =	Math.sin (t);
		yM = (int) ((double) rx4 * z * z * z);
	}

	public void actionPerformed (ActionEvent e) {
		if (e.getSource() == recule)
			dt = adt;
		else if (e.getSource() == avance)
			dt = -adt;
		else if (e.getSource() == stop)
			dt = 0;
		else if (e.getSource() == tr)
			btrace = !btrace;
		adt = Math.abs (Double.parseDouble(TFadt.getText()));
		DT = Math.abs (Integer.parseInt (TFDT.getText()));
	}

	public static void main (String [] args) {
		astro a = new astro();
		JFrame f = new JFrame ("Astroïde");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (a);
		f.setSize (500, 500);
		f.setVisible (true);
	}

}
