package sample.svg.contributed;
import static util.Generic3DUtil.*;

public class Nagae3 {
	private static final double  P = 10.0;
	private static final double  R = 28.0;
	private static final double  B = 2.6666667;

	private static double dfXdT(double t, double x, double y, double z) {
		return (P)*((y) - (x)) + (t);
	}

	private static double dfYdT(double t, double x, double y, double z) {
		return (R)*(x) - (x)*(z) - (y);
	}

	private static double dfZdT(double t, double x, double y, double z) {
		return (x)*(y) - (B)*(z) - (t);
	} 

	private static void rungekutta(
			double t0, double tx, int cnt,
			double x0, double y0, double z0
			) {
		int i;
		double dt = (tx - t0) / cnt;

		double       told = t0;
		double xnew, xold = x0;
		double ynew, yold = y0;
		double znew, zold = z0;

		for (i = 1; i <= cnt; i++) {
			double kx1 = dt*dfXdT(told, xold, yold, zold);
			double ky1 = dt*dfYdT(told, xold, yold, zold);
			double kz1 = dt*dfZdT(told, xold, yold, zold);

			double kx2 = dt*dfXdT(told + dt/2, xold + kx1/2, yold + ky1/2, zold + kz1/2);
			double ky2 = dt*dfYdT(told + dt/2, xold + kx1/2, yold + ky1/2, zold + kz1/2);
			double kz2 = dt*dfZdT(told + dt/2, xold + kx1/2, yold + ky1/2, zold + kz1/2);

			double kx3 = dt*dfXdT(told + dt/2, xold + kx2/2, yold + ky2/2, zold + kz2/2);
			double ky3 = dt*dfYdT(told + dt/2, xold + kx2/2, yold + ky2/2, zold + kz2/2);
			double kz3 = dt*dfZdT(told + dt/2, xold + kx2/2, yold + ky2/2, zold + kz2/2);

			double kx4 = dt*dfXdT(told + dt/2, xold + kx3, yold + ky3, zold + kz3);
			double ky4 = dt*dfYdT(told + dt/2, xold + kx3, yold + ky3, zold + kz3);
			double kz4 = dt*dfZdT(told + dt/2, xold + kx3, yold + ky3, zold + kz3);

			xnew = xold + (kx1 + kx2*2 + kx3*2 + kx4)/6;
			ynew = yold + (ky1 + ky2*2 + ky3*2 + ky4)/6;
			znew = zold + (kz1 + kz2*2 + kz3*2 + kz4)/6;

			vertex(xnew, ynew, znew);

			xold = xnew;
			yold = ynew;
			zold = znew;

			told = t0 + dt*i;
		}
	}

	public static void main(String[] args) {
		int step = 160;
		start();
		strokeWeight(0.5);
		stroke(0x00ff4f);
		beginShape();
		rungekutta(0, step, step*200, 1, 1, 1);
		endShape();
		
		finish();
		return;
	}
}