import java.applet.*;
import java.awt.*;
import java.awt.event.*;

/*
<applet code="Bezier.class" width=480 height=480>
</applet>
*/

public class Bezier extends Applet
{
    static int WIDTH, HEIGHT;        // 画面サイズ
    Point point[][];                 // 制御点
    int point_num = 0;               // 制御点の番号
    int captured_point = -1;         // つかんでいる制御点の番号
                                     //（-1のときつかんでいない）
    boolean capture_mode_FLG;        // 線を制御できるかを表すフラグ

    static final int point_data[][][] =    // 点情報
        {
            { {157, 200}, { 65, 236}, { 35, 277}, { 23, 479},},
            { {178, 141}, {167, 163}, {162, 184}, {157, 200},},
            { {339, 180}, {326, 157}, {312, 148}, {292, 145},},
            { {187,  31}, {174,  37}, {168,  42}, {167,  49},},
            { {167,  49}, {157,  57}, {153,  69}, {156,  77},},
            { {156,  77}, {149,  85}, {150,  96}, {155, 104},},
            { {156, 103}, {153, 115}, {161, 126}, {169, 129},},
            { {188,  31}, {208,  31}, {236,  28}, {249,  24},},
            { {249,  24}, {271,  27}, {278,  35}, {286,  48},},
            { {286,  48}, {292,  52}, {294,  61}, {291,  68},},
          //10
            { {291,  68}, {297,  78}, {296,  87}, {287,  99},},
            { {190,  29}, {209,  20}, {227,  17}, {249,  23},},
            { {194,  54}, {220,  42}, {245,  38}, {268,  40},},
            { {195,  54}, {188,  82}, {198, 120}, {206, 148},},
            { {268,  39}, {279,  56}, {284,  72}, {283,  94},},
            { {283,  94}, {289,  99}, {290, 118}, {290, 135},},
            { {289, 134}, {293, 141}, {294, 154}, {293, 165},},
            { {293, 164}, {292, 180}, {275, 180}, {265, 182},},
            { {264, 181}, {239, 177}, {223, 170}, {208, 162},},
            { {209, 162}, {202, 157}, {200, 153}, {198, 146},},
          //20
            { {198, 145}, {201, 140}, {200, 135}, {194, 132},},
            { {194, 132}, {191, 127}, {189, 124}, {191, 120},},
            { {190, 119}, {187, 109}, {177, 104}, {171, 112},},
            { {172, 111}, {164, 116}, {166, 123}, {168, 129},},
            { {168, 129}, {173, 135}, {179, 144}, {188, 145},},
            { {188, 145}, {191, 147}, {195, 147}, {199, 142},},
            { {206, 148}, {212, 155}, {223, 160}, {241, 162},},
            { {241, 162}, {240, 148}, {245, 134}, {257, 128},},
            { {257, 128}, {259, 128}, {260, 129}, {262, 131},},
            { {262, 131}, {243, 146}, {241, 179}, {265, 168},},
          //30
            { {264, 167}, {269, 163}, {266, 155}, {262, 149},},
            { {277, 147}, {268, 198}, {311, 132}, {267, 130},},
            { {268, 129}, {268, 127}, {269, 126}, {271, 126},},
            { {270, 127}, {278, 124}, {286, 128}, {289, 135},},
            { {255, 146}, {264, 154}, {279, 149}, {281, 138},},
            { {255, 146}, {260, 138}, {264, 134}, {268, 137},},
            { {268, 137}, {272, 132}, {278, 134}, {281, 138},},
            { {255, 146}, {262, 141}, {272, 144}, {281, 138},},
            { {272, 119}, {269, 105}, {265,  99}, {262,  94},},
            { {272, 119}, {270, 121}, {270, 126}, {268, 125},},
          //40
            { {268, 124}, {262, 127}, {254, 118}, {255, 125},},
            { {254, 124}, {249, 127}, {247, 121}, {250, 115},},
            { {241,  84}, {226,  81}, {218,  88}, {212,  98},},
            { {264,  80}, {271,  74}, {275,  74}, {281,  77},},
            { {244,  93}, {236,  87}, {224,  92}, {219, 100},},
            { {263,  89}, {269,  82}, {275,  80}, {282,  83},},
            { {243,  98}, {237,  93}, {229,  94}, {222, 106},},
            { {243,  99}, {238, 106}, {230, 105}, {222, 107},},
            { {264,  93}, {270,  85}, {278,  84}, {283,  87},},
            { {264,  94}, {272,  96}, {280,  96}, {283,  88},},
          //50
            { {193, 147}, {206, 172}, {241, 192}, {270, 188},},
            { {274, 179}, {272, 183}, {271, 185}, {269, 190},},
            { {188, 146}, {196, 177}, {226, 202}, {261, 204},},
            { {272, 193}, {268, 197}, {264, 200}, {259, 204},},
            { {271, 192}, {276, 195}, {278, 195}, {284, 195},},
            { {283, 194}, {287, 187}, {289, 181}, {288, 176},},
            { {177, 142}, {185, 176}, {203, 205}, {234, 223},},
            { {234, 224}, {263, 210}, {273, 227}, {258, 259},},
            { {197, 353}, {184, 391}, {181, 430}, {179, 479},},
            { {322, 329}, {355, 360}, {363, 406}, {362, 479},},
          //60
            { {197, 352}, {212, 341}, {226, 336}, {241, 330},},
            { {181, 436}, {222, 415}, {257, 391}, {280, 360},},
            { {241, 330}, {247, 348}, {260, 363}, {278, 361},},
            { {278, 360}, {284, 355}, {284, 351}, {281, 348},},
            { {242, 331}, {244, 330}, {246, 328}, {249, 326},},
            { {248, 327}, {254, 344}, {270, 354}, {281, 349},},
            { {249, 330}, {253, 302}, {260, 281}, {262, 262},},
            { {262, 262}, {265, 240}, {273, 241}, {276, 257},},
            { {276, 257}, {278, 265}, {273, 275}, {275, 285},},
            { {275, 284}, {282, 278}, {290, 277}, {295, 275},},
          //70
            { {295, 276}, {306, 262}, {310, 253}, {312, 240},},
            { {312, 240}, {318, 225}, {327, 232}, {321, 245},},
            { {322, 243}, {321, 257}, {317, 269}, {306, 286},},
            { {307, 286}, {321, 273}, {324, 262}, {329, 243},},
            { {329, 243}, {337, 226}, {345, 233}, {340, 247},},
            { {340, 246}, {337, 256}, {337, 266}, {333, 273},},
            { {333, 273}, {328, 282}, {321, 291}, {318, 296},},
            { {338, 252}, {346, 242}, {351, 244}, {347, 258},},
            { {347, 257}, {345, 263}, {346, 269}, {343, 279},},
            { {344, 276}, {340, 287}, {337, 295}, {327, 304},},
          //80
            { {326, 305}, {339, 301}, {349, 291}, {353, 285},},
            { {353, 285}, {360, 277}, {368, 285}, {357, 293},},
            { {358, 291}, {351, 307}, {335, 315}, {323, 319},},
            { {323, 318}, {312, 332}, {299, 341}, {281, 350},},
            { {296, 278}, {299, 283}, {300, 285}, {303, 285},},
            { {308, 288}, {310, 291}, {312, 294}, {315, 294},},
            { {319, 298}, {319, 301}, {324, 307}, {322, 304},},
            { {324, 307}, {326, 310}, {325, 312}, {325, 314},},
            { {365, 339}, {346, 334}, {332, 331}, {312, 329},},
            { {361, 425}, {310, 402}, {290, 379}, {278, 362},},
          //90
            { {196, 352}, {185, 349}, {173, 351}, {167, 356},},
            { {262, 268}, {257, 258}, {255, 255}, {253, 252},},
            { {254, 252}, {250, 234}, {238, 239}, {240, 257},},
            { {240, 257}, {245, 265}, {247, 273}, {251, 280},},
            { {250, 280}, {240, 278}, {232, 277}, {224, 280},},
            { {223, 280}, {217, 280}, {211, 279}, {207, 280},},
            { {207, 280}, {198, 270}, {195, 264}, {192, 260},},
            { {192, 261}, {186, 247}, {177, 256}, {185, 271},},
            { {185, 271}, {188, 281}, {199, 294}, {215, 295},},
            { {184, 268}, {173, 253}, {163, 258}, {173, 275},},
          //100
            { {173, 275}, {181, 297}, {197, 309}, {214, 311},},
            { {173, 275}, {168, 272}, {162, 281}, {168, 287},},
            { {168, 287}, {175, 305}, {189, 317}, {211, 322},},
            { {209, 321}, {190, 322}, {181, 314}, {176, 313},},
            { {177, 313}, {165, 302}, {159, 313}, {171, 321},},
            { {171, 321}, {189, 336}, {208, 335}, {228, 333},},
            { {293, 273}, {277, 206}, {316, 184}, {336, 215},},
            { {336, 216}, {364, 215}, {368, 250}, {346, 265},},
            { {347, 217}, {391, 246}, {295, 148}, {425, 271}, {336, 187}, 
{374, 204},},
            { {348, 217}, {374, 229}, {302, 155}, {417, 254}, {334, 190}, 
{372, 203},},
          //110
            { {360, 239}, {355, 184}, {397, 311}, {352, 146}, {385, 258}, 
{385, 220},},
            { {361, 241}, {361, 196}, {397, 315}, {355, 155}, {387, 265}, 
{384, 221},},
            { {361, 240}, {355, 278}, {404, 189}, {333, 329}, {390, 228}, 
{377, 268},},
            { {357, 251}, {350, 282}, {404, 191}, {323, 336}, {389, 236}, 
{376, 267},},
            { {352, 259}, {332, 290}, {406, 239}, {295, 299}, {379, 266}, 
{353, 281},},
            { {345, 272}, {345, 272}, {369, 261}, {316, 303}, {364, 269}, 
{354, 280},},
            { {329, 206}, {348, 199}, {289, 176}, {379, 205}, {322, 181}, 
{338, 180},},
            { {324, 202}, {343, 197}, {289, 174}, {369, 202}, {312, 174}, 
{341, 180},},
            { {318, 200}, {301, 195}, {354, 185}, {269, 184}, {335, 182}, 
{308, 175},},
            { {311, 200}, {298, 194}, {348, 183}, {266, 185}, {324, 182}, 
{309, 175},},
          //120
            { {301, 206}, {281, 215}, {315, 173}, {272, 212}, {284, 192}, 
{284, 192},},
            { {294, 212}, {280, 219}, {309, 179}, {266, 215}, {284, 192}, 
{284, 192},},
            { {292, 219}, {274, 236}, {288, 178}, {260, 256}, {274, 201}, 
{261, 217},},
            { {290, 226}, {276, 237}, {285, 186}, {257, 260}, {275, 206}, 
{262, 215},},
            { {289, 234}, {284, 251}, {278, 231}, {271, 248},},
            { {289, 243}, {284, 256}, {277, 237}, {273, 251},},
            { {290, 258}, {282, 253}, {282, 270}, {276, 262},},
            { {291, 266}, {285, 254}, {282, 277}, {276, 277},},
            { {361, 240}, {422, 280}, {450, 341}, {450, 479},},
            { {163, 204}, {179, 229}, {202, 249}, {232, 255},},
          //130
            { {271, 194}, {270, 202}, {270, 209}, {271, 219},},
            { {271, 224}, {270, 231}, {270, 237}, {270, 245},},
            { {326, 192}, {324, 194}, {322, 197}, {321, 201},},
            { {217, 419}, {250, 404}, {290, 403}, {332, 417},},
            { {251, 398}, {267, 392}, {279, 392}, {293, 396},},
            { {258, 408}, {245, 428}, {243, 451}, {247, 478},},
            { {293, 408}, {300, 434}, {302, 447}, {303, 467},},
            { {315, 434}, {321, 452}, {323, 462}, {327, 479},},
            { {234,  96}, {232,  99}, {234, 102}, {237, 102},},
            { {237, 102}, {240,  98}, {241,  98}, {238,  96},},
          //140
            { {273,  85}, {272,  94}, {274,  91}, {277,  93},},
            { {277,  92}, {280,  90}, {281,  89}, {278,  85},},
            { {187, 145}, {201, 195}, {263, 205}, {262, 223},},
         };

    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 = d.width; HEIGHT = d.height;

        Button increment, decrement, modify;
        increment = new Button("increment");          // 画面設定
        decrement = new Button("decrement");
        modify = new Button("modify");
        tf = new Label(Integer.toString(point_num));
        add(modify);
        add(increment);
        add(decrement);
        add(tf);

        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();
            }
        });

        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 &&
                       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 i, j;
        double x1, x2, y1, y2;
        double bernstein[] = new double[point.length];
        x1 = point[0].x;
        y1 = point[0].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];
            }

            g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
            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);
            }
        }

        for(int i = 0; i < point.length; i++)     // 曲線描画
        {
            if(capture_mode_FLG && point_num == i)
                BezierCurve(offg, Color.blue, point[i]);
            else BezierCurve(offg, Color.black, point[i]);
        }

        g.drawImage(offi, 0, 0, this);
    }

    public void update(Graphics g)
    {
        paint(g);
    }
}

