/*
  2003/07/28 小松 研吾
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Magline3 extends Applet implements ActionListener {
    Button bt1, bt2, bt3;
    int c = 0;

    public void init() {
	// Layoutを無効にする。
	// 無効にしないと、既にあるLayoutによって
	// 勝手にコンポーネントが配置されてしまう。
	setLayout(null);

	// ボタンを配置
	bt1 = new Button("Euler法");
	add(bt1);
	bt1.setBounds(5, 5, 50, 20);
	bt1.addActionListener(this);

	bt2 = new Button("Runge-Kutta法");
	add(bt2);
	bt2.setBounds(60, 5, 90, 20);
	bt2.addActionListener(this);

	bt3 = new Button("clear");
	add(bt3);
	bt3.setBounds(155, 5, 50, 20);
	bt3.addActionListener(this);
    }

    // ボタンが押されたときに呼び出されるメソッド
    public void actionPerformed(ActionEvent ev) {
	// どのオブジェクトに関するイベントかを取得する。
	Object obj = ev.getSource();
	if (obj == bt1) {
	    // bt1のボタンが押されたとき...
	    c = 1;
	    repaint();
	} else if (obj == bt2) {
	    // bt2のボタンが押されたとき...
	    c = 2;
	    repaint();
	} else if (obj == bt3) {
	    // bt3のボタンが押されたとき...
	    c = 3;
	    repaint();
	}
    }

    /*
    // update()をオーバーライドしアプレットをリフレッシュしない
    public void update(Graphics g) {
	paint(g);
    }
    */

    public void paint(Graphics g) {
	// 変数宣言
	Dimension d = getSize();
	Color color = Color.red;
	int width = d.width;
	int height = d.height;
	int oldpltX, oldpltY, pltX, pltY;
	double h, theta, r, dr, R, k1, k2, k3, k4;

	// 変位量
	h = 0.01;
	// 初期化
	r = 1; dr = 0; R = 0;
	k1 = 0; k2 = 0; k3 = 0; k4 = 0;
	oldpltX = 0; oldpltY = 0; pltX = 0; pltY = 0 ;

	// 背景色
	setBackground(Color.white);
	g.setColor(Color.blue);
	// 表示域の周囲に四角形を描画
	g.drawRect(0, 0, width-1, height-1);
	// x軸を描画
	g.drawLine(0, height/2, width-1, height/2);
	// 惑星半径を単位とした目盛りを描画
	for(int i=2; i<=10 ; ++i)
	    g.drawLine(50*i, height/2-10, 50*i, height/2+10);
	// 惑星を描画（半径50pixelsの円）
	g.fillOval(-50, height/2-50, (int)(r/h), (int)(r/h));

	// 始点
	theta = Math.PI / 12;
	for(int i=0; i<5; ++i) { // 複数の磁力線を描画
	    // 始点を表示域の座標に変換
	    oldpltX = (int)(r/(2*h) * Math.sin(theta));
	    oldpltY = height/2 - (int)(r/(2*h) * Math.cos(theta));

	    R = 1 / (Math.sin(theta)*Math.sin(theta));
	    for(int j=0; j<width; j++) {
		// 真の解
		r = R*Math.sin(theta)*Math.sin(theta);

		// データ値を表示域の座標に変換し曲線を描画
		pltX = (int)(r/(2*h) * Math.sin(theta));
		pltY = height/2 - (int)(r/(2*h) * Math.cos(theta));
		color = Color.red;
		g.setColor(color);
		g.drawLine(oldpltX, oldpltY, pltX, pltY);
		oldpltX = pltX;
		oldpltY = pltY;

		theta += h;

		// 惑星表面で線を打ち切る
		if(r<1)
		    break;
	    }
	    // 次の磁力線の始点
	    r = 1;
	    theta = (double)(i+1) * (Math.PI/12);
	}

	if(c==1 | c==2) {
	    // 始点
	    theta = Math.PI / 12;
	    for(int i=0; i<5; ++i) { // 複数の磁力線を描画
		// 始点を表示域の座標に変換
		oldpltX = (int)(r/(2*h) * Math.sin(theta));
		oldpltY = height/2 - (int)(r/(2*h) * Math.cos(theta));

		for(int j=0; j<width; j++) {
		    if(c==1) { // Euler法
			r += f(theta, r)*h;
		    } else if(c==2) { // Runge-Kutta法
			k1 = h * f(theta, r);
			k2 = h * f(theta+h/2, r+k1/2);
			k3 = h * f(theta+h/2, r+k2/2);
			k4 = h * f(theta+h, r+k3);
			dr = (k1 + 2*k2 + 2*k3 + k4) / 6.0;
		    }

		    // データ値を表示域の座標に変換し曲線を描画
		    pltX = (int)(r/(2*h) * Math.sin(theta));
		    pltY = height/2 - (int)(r/(2*h) * Math.cos(theta));
		    if(c==1) {
			color = Color.green;
		    } else if(c==2) {
			color = Color.black;
		    }
		    g.setColor(color);
		    g.drawLine(oldpltX, oldpltY, pltX, pltY);
		    oldpltX = pltX;
		    oldpltY = pltY;

		    if(c==1) {
			theta += h;
		    } else if(c==2) {
			r += dr;
			theta += h;
		    }

		    // 惑星表面で線を打ち切る
		    if(r<1)
			break;
		}
		// 次の磁力線の始点
		r = 1;
		theta = (double)(i+1) * (Math.PI/12);
	    }
	} else if(c==3) { // clear
	    
	}
    }

    private double f(double theta, double r) {
	double value = 0;
	value = r * (2*Math.cos(theta) / Math.sin(theta));
	return value;
    }
}
