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

public class Sampler extends Applet implements Runnable 
{
    Thread kicker;
    double Pi = 3.14159265;
    float s1, c1, s2, c2, s3, c3;
    float a, b, c, k, mu, q, w, R;
    float m[][] = new float[4][4];
    float r[][] = new float[4][4];
    float v[] = new float[4];
    float u[] = new float[4];
    int hor, ver, hor0, ver0;

    public void init() 
    {
	a = b = c = k = q = 0;
	mu = (float) Pi/6;
	s1 = s2 = s3 = 0;
	c1 = c2 = c3 = 1;
	w = (float) Pi/32;
	R = 8;
	resize(200, 200);
	hor0 = ver0 = 100;
    }
    
    public void paint(Graphics g) 
    {
	setAngles(a, b, c);
	setMatrix();
	setRotation();
	g.setColor(Color.white);
	int rad = (int) R;
	g.drawLine(100 - 3 * rad, 100 + 2 * rad, 100+ 3 * rad, 100 - 2 * rad);
	g.setColor(Color.black);	
	for (int t = -100; t < 100; t++) {
	    setVector(t);
	    setUnit();
	    hor = (int) (5 * u[1] - 3 * u[3] + hor0 + .5);
	    ver = (int) (2 * (u[1] + u[3]) - 7 * u[2] + ver0 + .5);
	    g.drawLine(hor, ver, hor, ver);
	}
    }
    
    private void setAngles(float A, float B, float C)
    {
	s1 = (float) Math.sin(A * Pi / 180);
	c1 = (float) Math.cos(A * Pi / 180);
	s2 = (float) Math.sin(B * Pi / 180);
	c2 = (float) Math.cos(B * Pi / 180);
	s3 = (float) Math.sin(C * Pi / 180);
	c3 = (float) Math.cos(C * Pi / 180);
    }
    
    private void setMatrix() 
    {
	m[1][1] = c2 * c2 * c1 + s2 * s2;
	m[1][2] = c2 * s2 * (c1 - 1);
	m[1][3] = c2 * s1;
	m[2][1] = m[1][2];
	m[2][2] = c2 * c2 + s2 * s2 * c1;
	m[2][3] = s2 * s1;
	m[3][1] = -m[1][3];
	m[3][2] = -m[2][3];
	m[3][3] = c1;
    }
    
    private void setRotation()
    {
	r[1][1] = m[1][1] * c3 - m[2][1] * s3;
	r[1][2] = m[1][2] * c3 - m[2][2] * s3;
	r[1][3] = m[1][3] * c3 - m[2][3] * s3;
	r[2][1] = m[1][1] * s3 + m[2][1] * c3;
	r[2][2] = m[1][2] * s3 + m[2][2] * c3;
	r[2][3] = m[1][3] * s3 + m[2][3] * c3;
	r[3][1] = m[3][1];
	r[3][2] = m[3][2];
	r[3][3] = m[3][3];
    }
    
    private void setVector(float T)
    {
	float axis = k + w * T * (float) Math.tan(mu);
	float r = R / (float) Math.sqrt(1 + axis * axis);
	v[1] = r * (float) Math.cos(q + w * T);
	v[2] = r * (float) Math.sin(q + w * T);
	v[3] = r * axis;
    }
    
    private void setUnit() 
    {
	u[1] = r[1][1] * v[1] + r[1][2] * v[2] + r[1][3] * v[3];
	u[2] = r[2][1] * v[1] + r[2][2] * v[2] + r[2][3] * v[3];
	u[3] = r[3][1] * v[1] + r[3][2] * v[2] + r[3][3] * v[3];	
    }
    
    public void start() 
    {
	kicker = new Thread(this);
	kicker.start();
    }
    
    public void stop() 
    {
	kicker = null;
    }
    
    public void run() 
    {
	Thread me = Thread.currentThread();
	while (kicker == me) {
	    try 
		{
		    Thread.currentThread().sleep(10);
		}
	    catch (InterruptedException e) 
		{
		}
	    repaint();
	}
    }
    
    public void update(Graphics g) 
    {
	paint(g);
    }
}



