import java.applet.*;
import java.awt.*;
import java.awt.event.*;

/*
<applet code="Bezier.class" width=480 height=480>
</applet>
*/

public class m0104020_4 extends Applet
{
	static int WIDTH, HEIGHT;			// 画面サイズ
	Point point[][];							// 制御点
	int point_num = 0;						// 制御点の番号


	static final int point_data[][][] =		// 点情報
	{
		{ 	{60,10},	{58,16},	{50,20},  {50,30},	},	//葉っぱ(上左)
		{ 	{60,10},	{62,16},	{70,20},  {70,30},	},	//葉っぱ(上右)
		{ 	{40,32},	{46,26},	{50,30}, 	},	//葉っぱ(中左)
		{ 	{70,30},	{74,26},	{80,32}, 	},	//葉っぱ(中右)
		{ 	{39,32},	{44,52},	{60,40},  },	//葉っぱ(下左)
		{ 	{81,32},	{76,52},	{60,40}, 	},	//葉っぱ(下右)
    };

    Label tf;

    Graphics offg, backg;
    Image    offi, backi;

    public void initialize()	// 制御点の設定
    {
        int i;
        point = new Point[point_data.length][];

        for(i = 0; i < point.length; i++)
        {
            point[i] = new Point[point_data[i].length];
            for(int j = 0; j < point_data[i].length; j++)
                point[i][j] = new Point(point_data[i][j][0],
                                        point_data[i][j][1]);
        }
    }

    public void init()
    {
        Dimension d = getSize();
        WIDTH = 800; HEIGHT = 600;


        initialize();

        offi = createImage(WIDTH, HEIGHT);
        offg = offi.getGraphics();
        backi = createImage(WIDTH, HEIGHT);
        backg = backi.getGraphics();
        setBackImage(backg);

		// テスト
        addKeyListener(new KeyAdapter()
        {
            public void keyPressed(KeyEvent ke)
            {
                int c = ke.getKeyCode();
                if(c == 'P')
                {
                    System.out.println("{");
                    for(int i = 0; i < point[point_num].length; i++)
                        System.out.println(""+point[point_num][i].x
                                        +", "+point[point_num][i].y);
                    System.out.println("},");
                }
                else if(c == 'B')
                {
                    repaint();
                }
            }
        });
    }

    public void setBackImage(Graphics g)	// 背景の用意
    {
        g.setColor(new Color(231,255,200));
        g.fillRect(0, 0, WIDTH, HEIGHT);



      	g.setColor(Color.black);
        g.drawRect(0, 0, WIDTH-1, HEIGHT-1);  // 枠描画
    }

    public int kaijyo(int num)	// 階乗を計算
    {
        int total = 1;

        if(num == 0) return 1;

        for(; num > 1; num--)
            total *= num;
        return total;
    }

    public void BezierCurve(Graphics g, Color color, Point point[])  // 曲線描画
    {
        int i, j;
        double x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7, x8, y8;
        double xx1, xx2, xx3, xx4, yy1, yy2, yy3, yy4, xx5, yy5, xx6, yy6, xx7, yy7, xx8, yy8;
        double d=Math.PI/4;
        double bernstein[] = new double[point.length];
        x1 = point[0].x;
        y1 = point[0].y;

		double x=58;
	    double y=48;
	    double radio=15;
	    double to=0;
	    double xx=radio*Math.cos(to)+x;
	    double yy=radio*Math.sin(to)+y;



        g.setColor(color);

        for(double t = 0; t <= 1; t += 0.01)
        {
            for(i = 0; i < point.length; i++)        // bernstein関数を計算
            {
                bernstein[i] = (double)kaijyo(point.length-1)
                            / (kaijyo(i)*kaijyo(point.length-1-i));

                for(j = 1; j <= i; j++) bernstein[i] *= t;
                for(j = 1; j <= point.length-1-i; j++) bernstein[i] *= (1-t);
            }

            x2 = y2 = 0;
            for(i = 0; i < point.length; i++)
            {
                x2 += point[i].x * bernstein[i];
                y2 += point[i].y * bernstein[i];
            }

            x3 = x1*Math.cos(Math.PI/2)-y1*Math.sin(Math.PI/2)+110;
            x4 = x2*Math.cos(Math.PI/2)-y2*Math.sin(Math.PI/2)+110;

            y3 = x1*Math.sin(Math.PI/2)+y1*Math.cos(Math.PI/2)-10 ;
            y4 = x2*Math.sin(Math.PI/2)+y2*Math.cos(Math.PI/2)-10 ;

            x5 = x3*Math.cos(Math.PI/2)-y3*Math.sin(Math.PI/2)+110;
			x6 = x4*Math.cos(Math.PI/2)-y4*Math.sin(Math.PI/2)+110;

			y5 = x3*Math.sin(Math.PI/2)+y3*Math.cos(Math.PI/2)-10 ;
            y6 = x4*Math.sin(Math.PI/2)+y4*Math.cos(Math.PI/2)-10 ;

			x7 = x5*Math.cos(Math.PI/2)-y5*Math.sin(Math.PI/2)+110;
			x8 = x6*Math.cos(Math.PI/2)-y6*Math.sin(Math.PI/2)+110;

			y7 = x5*Math.sin(Math.PI/2)+y5*Math.cos(Math.PI/2)-10 ;
            y8 = x6*Math.sin(Math.PI/2)+y6*Math.cos(Math.PI/2)-10 ;


			for(int k=0; k<9; k++){
				for(int l=0; l<7; l++){

					xx1 = x1 + 80*k;
					yy1 = y1 + 80*l;
					xx2 = x2 + 80*k;
					yy2 = y2 + 80*l;
					xx3 = x3 + 80*k;
					yy3 = y3 + 80*l;
					xx4 = x4 + 80*k;
					yy4 = y4 + 80*l;
					xx5 = x5 + 80*k;
					yy5 = y5 + 80*l;
					xx6 = x6 + 80*k;
					yy6 = y6 + 80*l;
					xx7 = x7 + 80*k;
					yy7 = y7 + 80*l;
					xx8 = x8 + 80*k;
					yy8 = y8 + 80*l;

                    g.drawLine((int)xx1, (int)yy1, (int)xx2, (int)yy2);
                    g.drawLine((int)xx3, (int)yy3, (int)xx4, (int)yy4);
                    g.drawLine((int)xx5, (int)yy5, (int)xx6, (int)yy6);
					g.drawLine((int)xx7, (int)yy7, (int)xx8, (int)yy8);

					for(to=0;to<=6.2832;to+=0.8){
								double xxo=radio*Math.cos(to)+x+80*k;
								double yyo=radio*Math.sin(to)+y+80*l;


								g.fillOval((int)xxo,(int)yyo, 5, 5);


							}

				}
			}

            x1 = x2;
            y1 = y2;

        }
    }

    public void paint(Graphics g)
    {
        requestFocus();
        offg.drawImage(backi, 0, 0, this);  // 背景の描画



        for(int i = 0; i < point.length; i++)     // 曲線描画
        {
           BezierCurve(offg, new Color(125,125,20), point[i]);
        }

        g.drawImage(offi, 0, 0, this);
    }

    public void update(Graphics g)
    {
        paint(g);
    }
}
