import java.applet.*;
import java.awt.*;
import java.awt.event.*;


public class m0104304_04 extends Applet
{
    static int WIDTH, HEIGHT;        // 画面サイズ
    Point point[][];                 // 制御点
    int point_num = 0;               // 制御点の番号
    int captured_point = -1;         // つかんでいる制御点の番号
                                     //（-1のときつかんでいない）
    boolean capture_mode_FLG;        // 線を制御できるかを表すフラグ

	boolean swichi;					//解説を表示しているかを表すフラグ



	static final int fontsize[]={2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; //線の太さの初期値

	static final int point_data[][][] =    // 点情報
        {


		{ {185,265}, {145,195}, {70,175}, },//羽
				{ {70,175}, {60,185}, {55,205}, },
				{ {55,205}, {60,235}, {55,250}, },
				{ {205,272}, {165,195}, {120,165}, },

				{ {120,165}, {105,160}, {105,190}, },


				{ {185,265}, {180,262}, {175,270}, },
				{ {185,265}, {205,270}, {225,282}, },//顔とはね
				{ {225,282}, {230,286}, {245,302}, },

				{ {245,302}, {240,307}, {225,302}, },//口
				{ {225,302}, {220,310}, {215,309}, },
				{ {215,309}, {190,334}, {175,324}, },
				{ {175,324}, {165,344}, {85,364}, },
				{ {85,364}, {70,360}, {55,345}, },
				{ {55,345}, {45,324}, {48,314}, },
				{ {48,314}, {45,304}, {40,294}, },
				{ {40,294}, {45,284}, {50,279}, },
				{ {50,279}, {40,269}, {40,265}, },
				{ {40,265}, {45,240}, {105,250}, },
				{ {105,250}, {115,240}, {175,270}, },
				{ {175,270}, {165,275}, {155,290}, },
				{ {155,290}, {165,305}, {175,324}, },

				/*{ {155,490}, {135,505}, {58,514}, },//模様
				{ {155,490}, {135,505}, {90,554}, },
				{ {155,490}, {115,475}, {70,545}, },
				{ {155,490}, {115,475}, {60,479}, },
				*/
				{ {85,364}, {80,375}, {90,354}, },//模様
				{ {90,354}, {80,335}, {70,345}, },
				{ {70,345}, {80,325}, {58,314}, },
				{ {58,314}, {80,305}, {60,279}, },
				{ {60,279}, {80,275}, {75,247}, },
				{ {70,247}, {90,225}, {85,179}, },

				{ {225,282}, {255,270}, {305,282}, },//触覚
				{ {225,282}, {255,260}, {295,272}, },

				//{ {215,509}, {190,534}, {225,544}, },//足
				//{ {215,509}, {190,534}, {225,554}, },
				{ {195,324}, {220,314}, {235,324}, },
				{ {235,324}, {238,344}, {255,374}, },
				{ {215,315}, {230,314}, {245,324}, },
				{ {245,324}, {250,344}, {255,364}, },
				{ {185,328}, {185,354}, {195,370}, },
				{ {185,328}, {165,344}, {175,364}, },

	            { {230,418}, {255,355}, {295,340}, }, //花
	            { {245,435}, {245,360}, {295,340}, },
	            { {295,340}, {315,330}, {300,355}, },
	            { {245,420}, {280,360}, {320,360}, },
	            { {320,360}, {305,410}, {280,425}, },
	            { {310,390}, {330,370}, {360,360}, },
	            { {360,360}, {360,380}, {340,410}, },
	            { {280,460}, {335,405}, {385,385}, },
	            { {360,425}, {365,405}, {385,385}, },
	            { {360,425}, {345,455}, {315,470}, },
	            { {365,385}, {400,375}, {385,385}, },
	            { {345,335}, {310,335}, {285,370}, },
	            { {345,335}, {335,340}, {315,360}, },
	            { {345,335}, {350,335}, {340,350}, },
	            { {355,345}, {330,350}, {320,360}, },
	            { {355,345}, {350,360}, {340,370}, },
	            { {355,345}, {355,355}, {350,365}, },
	            { {375,345}, {360,350}, {355,355}, },
	            { {375,345}, {375,380}, {360,395}, },

	            { {175,545}, {175,480}, {160,395}, },//草
	            { {205,545}, {205,480}, {160,395}, },
	            { {275,545}, {205,480}, {270,455}, },
	            { {205,545}, {195,480}, {270,455}, },
	            { {175,545}, {175,480}, {100,395}, },
	            { {105,545}, {135,480}, {100,395}, },
	            { {75,545}, {75,480}, {80,395}, },
	            { {105,545}, {115,480}, {80,395}, },
			    { {75,545}, {75,480}, {20,355}, },
	            { {15,545}, {45,480}, {20,355}, },
	            { {275,545}, {205,480}, {370,455}, },
	            { {305,545}, {295,480}, {370,455}, },
	            { {375,545}, {405,480}, {570,405}, },
	            { {305,545}, {295,480}, {570,405}, },
	            { {375,545}, {405,480}, {490,495}, },
	            { {405,545}, {455,480}, {490,495}, },
	            { {435,545}, {405,500}, {500,555}, },
	            { {405,545}, {445,480}, {500,555}, },




    	};


    TextField zahyo;       // 曲線を指定する点の座標を表示

	Label tf;
	Graphics offg, backg, setumei, setumei2, setumei3, setumei4, setumei5;
    Image    offi, backi;
	Button kaisetu = new Button("名前の表示");		//説明のボタン


    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 = 800;

        Button increment, decrement, modify;

        increment = new Button("＜＜線の選択");          // 画面設定
        decrement = new Button("線の選択＞＞");
        modify = new Button("修正");

	tf = new Label(Integer.toString(point_num));  // 線の番号

	Button width_up = new Button("太くする");
	Button width_down = new Button("細くする");

	zahyo = new TextField("蝶＆花＆草", 50);		//座標表示用

		add(zahyo);
		add(modify);
        add(increment);
        add(decrement);
        add(tf);
		add(width_up);
	    add(width_down);
		add(kaisetu);


        increment.addActionListener(new ActionListener() // 制御点番号を増やす
        {
            public void actionPerformed(ActionEvent ae)
            {
                point_num++;
                if(point_num >= point.length)
                    point_num = 0;
                tf.setText(Integer.toString(point_num));
                repaint();
            }
        });

        decrement.addActionListener(new ActionListener()  // 制御点番号を減らす
        {
            public void actionPerformed(ActionEvent ae)
            {
                point_num--;
                if(point_num < 0) point_num = point.length-1;
                tf.setText(Integer.toString(point_num));
                repaint();
            }
        });

	kaisetu.addActionListener(new ActionListener()  // 解説表示を切り替える
	{
			public void actionPerformed(ActionEvent ae)
			{

			   if(swichi)
			   {
			   setumei = getGraphics();
			   setumei2 = getGraphics();
			   setumei3 = getGraphics();
			   setumei4 = getGraphics();
			   setumei5 = getGraphics();
			   setumei.drawString("",180,100);
			   setumei2.drawString("",180,114);
			   setumei3.drawString("",180,128);
			   setumei4.drawString("",180,142);
			   setumei5.drawString("",60,423);
			   kaisetu.setLabel("名前の表示");
			   swichi = !swichi;

			   repaint();

			   }
			   else
			   {
			   setumei = getGraphics();
			   setumei2 = getGraphics();
			   setumei3 = getGraphics();
			   setumei4 = getGraphics();
			   setumei5 = getGraphics();

			   setumei2.drawString("蝶",250,254);
			   setumei3.drawString("花",280,328);
			   setumei3.drawString("草",550,500);
			   kaisetu.setLabel("非表示");
			   swichi = !swichi;
			   }
			 }
		});

	width_up.addActionListener(new ActionListener()  // 線を太くする
	{
			public void actionPerformed(ActionEvent ae)
			{
				if(capture_mode_FLG){
					if(fontsize[point_num] == 7)
					fontsize[point_num] = 7;
					else
					fontsize[point_num]++;
				}
			repaint();
			}
	});

	width_down.addActionListener(new ActionListener()  // 線を細くする
	{
			public void actionPerformed(ActionEvent ae)
			{
				if(capture_mode_FLG){
					if(fontsize[point_num] == 1)
					fontsize[point_num] = 1;
					else
					fontsize[point_num]--;
				}
			repaint();
			}
	});



        modify.addActionListener(new ActionListener()  // モード変更
        {
            public void actionPerformed(ActionEvent ae)
            {
                capture_mode_FLG = !capture_mode_FLG;
                repaint();
            }
        });

        addMouseListener(new MouseAdapter()
        {
			public void mousePressed(MouseEvent me)    // 制御点をつかむ
            {
                int i, mx = me.getX(), my = me.getY();

                for(i = 0; i < point[point_num].length; i++)
                {
					if(point[point_num][i].x-3 <= mx &&
                       point[point_num][i].x+3 >= mx &&
                       point[point_num][i].y-3 <= my )
                       break;
                }
                if(i < point[point_num].length) captured_point = i;
            }

            public void mouseReleased(MouseEvent me)
            {
                captured_point = -1;
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() // 制御点を動かす
        {
            public void mouseDragged(MouseEvent me)
            {
                if(captured_point == -1) return;
                point[point_num][captured_point].setLocation(me.getX(), me.getY());
                repaint();
            }
        });

        initialize();

        offi = createImage(WIDTH, HEIGHT);
        offg = offi.getGraphics();
        backi = createImage(WIDTH, HEIGHT);
        backg = backi.getGraphics();
        setBackImage(backg);

        //test!
		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')
                {
                    // BezierCurve(backg, Color.black);
                    repaint();
                }
            }
        });
    }

    public void setBackImage(Graphics g)    // 背景の用意
    {
        g.setColor(Color.white);
        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 num)  // 曲線描画
    {
		Graphics2D g2=(Graphics2D)g;
        int i, j;
        double x1, x2, y1, y2;
        double bernstein[] = new double[point.length+1];
        x1 = point[0].x;
        y1 = point[0].y;

        g.setColor(color);
		g2.setStroke(new BasicStroke(fontsize[num]));

        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];
            }

            g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
             g.fillOval(210,280,15,15);
            x1 = x2;
            y1 = y2;
        }
    }



    public void paint(Graphics g)
    {
        requestFocus();
        offg.drawImage(backi, 0, 0, this);  // 背景の描画

        if(capture_mode_FLG)           // 制御点の描画
        {
            offg.setColor(Color.red);
            for(int i = 0; i < point[point_num].length; i++)
            {
                offg.fillRect(point[point_num][i].x-3,
                              point[point_num][i].y-3, 7, 7);

                offg.drawString(  Integer.toString(i+1),
                              point[point_num][i].x-3,
                              point[point_num][i].y-6);
			}

		zahyo.setText(	//座標の表示

			"{{"+ Integer.toString( point[point_num][0].x ) + "," + Integer.toString( point[point_num][0].y ) +"}," +
				"{" + Integer.toString( point[point_num][1].x ) + "," + Integer.toString( point[point_num][1].y ) + "}," +
				"{" + Integer.toString( point[point_num][2].x ) + "," + Integer.toString( point[point_num][2].y ) + "}},"
		);
	}



        for(int i = 0; i < point.length; i++)     // 曲線描画
        {
            if(capture_mode_FLG && point_num == i)
                BezierCurve(offg, Color.blue, point[i],i);
            else BezierCurve(offg, Color.black, point[i],i);
        }

        g.drawImage(offi, 0, 0, this);
    }

    public void update(Graphics g)
    {
        paint(g);
    }
}

