/**
 * trace une astroïde
 * 26/09/98 - double-buffering et adapté jdk 1.2 le 02/04/99
 *
 * @ author Jean-Paul Quelen
 * ajout de main() le 18/12/17 ; modifié le 15/09/22
 */

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class astrovar extends Panel implements Runnable, ActionListener {
	static final long serialVersionUID = 220915L;
	int xyMax, xy0, r, rx2, rx3, rx4, rx6, rx8, xy0mrx4, DT;
	int xM, yM, xM1, yM1, xC, yC, xC1, yC1, xy0m3r, 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 astrovar() {
		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 ="));
		add (TFadt = new TextField ("0.05", 10));
		add (TFDT = new TextField ("50", 10));
		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 = getSize().height; xy0 = getSize().width;
			xyMax = (xyMax > xy0 ? xy0 : xyMax);
			xy0 = xyMax / 2;
			r = xyMax / 8; rx4 = xyMax / 2; rx8 = xyMax; rx6 = xyMax * 3 / 4;
			xy0mrx4 = xy0 - rx4; xy0m3r = xy0 - xyMax * 3 / 8;
			xy0m2 = xy0 - 2;
			xC = r; yC = 0; xM = rx4; yM = 0;
			g.setColor (Color.WHITE);
			g.fillRect (0, 0, gw, gh);
		}

		g.setColor (Color.WHITE);
		g.drawOval (xy0m3r + xC1, xy0m3r + yC1, rx6, rx6);
		g.drawLine (xy0 + xC1, xy0 + yC1, xM1 + xy0, yM1 + xy0);
		if (!btrace)
			g.fillRect (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 (xy0m3r + xC, xy0m3r + yC, rx6, rx6);

		g.setColor (Color.BLUE);
//		g.drawLine (xy0 + xC, xy0 + yC, xM + xy0, yM + xy0);
		g.fillRect (xM + xy0m2, yM + xy0m2, epPoint, epPoint);

		g1.drawImage (img, 0, 0, this);

		xC1 = xC;
		yC1 = yC;
		xM1 = xM;
		yM1 = yM;
		t -= dt;
		xC = (int) (r * Math.cos (3.0 * t)); 
		yC = (int) (r * Math.sin (3.0 * 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) {
		astrovar a = new astrovar();
		JFrame f = new JFrame ("Astroïde - variante");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (a);
		f.setSize (500, 500);
		f.setVisible (true);
	}

}
