/* refeerence
* http://www.ke.ics.saitama-u.ac.jp/kondo/lect/cg/Bezier-koide/Bezier.java
* http://java.sun.com/j2se/1.4/ja/docs/ja/api/index.htmlおよび以下
*
*
* Vectorについて
* http://www.techscore.com/tech/Java/Utility/1.html
* 最終更新日 '05/5/31
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import java.net.URL;
/*
*/
public class BezierWriter extends Applet
implements MouseMotionListener,MouseListener
{
// --- Applet Propaty ---
static String title = "BezierWriter";
static int WIDTH, HEIGHT; // 画面サイズ
int cpn_w;// = 48; // コンパネサイズ
int cpn_h;
boolean cpnFlg = true; // コンパネ右、左
// --- Bezier Line ----
Vector curve = new Vector(); // 制御点
int point_num = 0; // 制御点の番号
int captured_point = -1; // つかんでいる制御点の番号
//(-1のときつかんでいない)
boolean capture_mode_FLG; // 線を制御できるかを表すフラグ
Bezier newBzr; // 追加用
int newBzrP = 0; //
int newBzrPoints = 3; // 追加の点数Dimension
int pen_x=-1,pen_y=-1;
int pen_red=0,pen_green=0,pen_blue=0;
Color pen_c=new Color(pen_red,pen_green,pen_blue);
boolean cooFlg = false; // 座標表示切り替え
boolean flushFlg = true; // backg初期化
int pen_breadth = 0; // 線幅
final char FM_CAP = 0;
final char FM_BRD = 1;
final char FM_DIM = 2;
final char FM_END = 3;
int fluc_mode = FM_CAP; //増減モード
final char M_ADD = 0;
final char M_MOD = 1;
final char M_PNT = 2;
final char M_DRW = 3;
final char M_PIC = 4;
final char M_END = 5;
int mode = M_ADD; //操作モード
// --- Graphics Variable ----
Graphics offg, backg , picg;
BufferedImage offi,backi;
Image pic;
boolean pic_on = false; //背景にBG.gifを表示
//---- Window Tool ----
Panel cpn_p;
String bName[]={"add","modify","paint","draw","picture"};
String bName2[]={"point_num","breadth","dimension"};
Button mode_b, increment, decrement, move_b
, fluc_b, coord_b , delete, clear, pic_b;
Scrollbar bar_r,bar_g,bar_b;
//[曲線b1...bn][点列a1...an][x,y]
// static final int point_data[][][] = // 点情報
Label tf; //数値表示用ラベル
/*
public void initialize(){ // 制御点の設定
System.out.println("initialize");
curve = new Vector();
for(int i=0; i>"); cpn_p.add(increment);
increment.setLocation(cpn_w/2,30); increment.setSize(cpn_w/2,30);
tf = new Label("CAT :"+Integer.toString(point_num));
cpn_p.add(tf); tf.setLocation(0,60); tf.setSize(cpn_w,30);
fluc_b = new Button(bName2[FM_CAP]); cpn_p.add(fluc_b);
fluc_b.setLocation(0,90); fluc_b.setSize(cpn_w,30);
coord_b = new Button("Coordinate"); cpn_p.add(coord_b);
coord_b.setLocation(0,120); coord_b.setSize(cpn_w,30);
delete = new Button("delete"); cpn_p.add(delete);
delete.setLocation(0,150); delete.setSize(cpn_w,30);
clear = new Button("clear"); cpn_p.add(clear);
clear.setLocation(0,180); clear.setSize(cpn_w,30);
move_b = new Button("move"); cpn_p.add(move_b);
move_b.setLocation(0,210); move_b.setSize(cpn_w,30);
pic_b = new Button("pic"); cpn_p.add(pic_b);
pic_b.setLocation(0,240); pic_b.setSize(cpn_w,30);
bar_r = new Scrollbar( Scrollbar.VERTICAL,255,1,0,255 );
cpn_p.add(bar_r); bar_r.setLocation(0,300); bar_r.setSize(cpn_w/3,150);
bar_g = new Scrollbar( Scrollbar.VERTICAL,255,1,0,255 );
cpn_p.add(bar_g); bar_g.setLocation(cpn_w/3,300); bar_g.setSize(cpn_w/3,150);
bar_b = new Scrollbar( Scrollbar.VERTICAL,255,1,0,255 );
cpn_p.add(bar_b); bar_b.setLocation(2*cpn_w/3,300); bar_b.setSize(cpn_w/3,150);
mode_b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ev){
System.out.println("mode_b");
mode++;
if( mode >= M_END )mode=M_ADD;
mode_b.setLabel(bName[mode]);
newBzrP = 0; //init
capture_mode_FLG = false;
if(mode==M_MOD){//modify
capture_mode_FLG = true;
}
repaint();
} });
increment.addActionListener(new ActionListener(){ // 制御点番号を増やす
public void actionPerformed(ActionEvent ae){
if(fluc_mode==FM_CAP){
point_num++;
if(point_num >= curve.size())
point_num = 0;
tf.setText("CAP: "+Integer.toString(point_num));
repaint();
}else if(fluc_mode==FM_BRD){
if(pen_breadth < 5)pen_breadth++;
tf.setText("BRD: "+Integer.toString(pen_breadth));
}else if(fluc_mode==FM_DIM){
if(newBzrPoints < Bezier.MAX_POINTS)newBzrPoints++;
tf.setText("DIM: "+Integer.toString(newBzrPoints-1));
}
} });
decrement.addActionListener(new ActionListener(){ // 制御点番号を減らす
public void actionPerformed(ActionEvent ae){
if(fluc_mode==FM_CAP){
point_num--;
if(point_num < 0) point_num = curve.size()-1;
tf.setText("CAP: "+Integer.toString(point_num));
repaint();
}else if(fluc_mode==FM_BRD){
if(pen_breadth > 0)pen_breadth--;
tf.setText("BRD: "+Integer.toString(pen_breadth));
}else if(fluc_mode==FM_DIM){
if(newBzrPoints > 3)newBzrPoints--;
tf.setText("DIM: "+Integer.toString(newBzrPoints-1));
}
} });
fluc_b.addActionListener(new ActionListener(){ // 制御点番号を減らす
public void actionPerformed(ActionEvent ae){
fluc_mode++;
if(fluc_mode>=FM_END)fluc_mode=0;
fluc_b.setLabel(bName2[fluc_mode]);
if(fluc_mode==FM_CAP)
tf.setText("CAP: "+Integer.toString(point_num));
else if(fluc_mode==FM_BRD)
tf.setText("BRD: "+Integer.toString(pen_breadth));
else if(fluc_mode==FM_DIM)
tf.setText("DIM: "+Integer.toString(newBzrPoints-1));
} });
coord_b.addActionListener(new ActionListener(){ // 座標表示
public void actionPerformed(ActionEvent ae){
cooFlg = !cooFlg; repaint();
} });
delete.addActionListener(new ActionListener(){ // delete
public void actionPerformed(ActionEvent ae){
if(mode==M_MOD){
curve.remove(point_num); point_num = 0;
tf.setText("CAP: 0"); repaint(); }
} });
clear.addActionListener(new ActionListener(){ // clear
public void actionPerformed(ActionEvent ae){
flushFlg = true; repaint();
} });
move_b.addActionListener(new ActionListener(){ // コンパネ移動
public void actionPerformed(ActionEvent ae){
cpnFlg = !cpnFlg;
if(cpnFlg){
cpn_p.setLocation(WIDTH-cpn_w,0);
}else{
cpn_p.setLocation(0,0);
}
flushFlg = true; repaint();
} });
pic_b.addActionListener(new ActionListener(){ // ピクチャon/off
public void actionPerformed(ActionEvent ae){
pic_on = !pic_on;
repaint();
} });
bar_r.addAdjustmentListener(new AdjustmentListener(){
public void adjustmentValueChanged(AdjustmentEvent ev){
pen_red = 255-ev.getValue();
pen_c=new Color(pen_red,pen_green,pen_blue);
fillSelectColor(); repaint();
}
});
bar_g.addAdjustmentListener(new AdjustmentListener(){
public void adjustmentValueChanged(AdjustmentEvent ev){
pen_green = 255-ev.getValue();
pen_c=new Color(pen_red,pen_green,pen_blue);
fillSelectColor(); repaint();
} });
bar_b.addAdjustmentListener(new AdjustmentListener(){
public void adjustmentValueChanged(AdjustmentEvent ev){
pen_blue = 255-ev.getValue();
pen_c=new Color(pen_red,pen_green,pen_blue);
fillSelectColor(); repaint();
} });
add(cpn_p);
cpn_p.setLocation(WIDTH-cpn_w,0);
addMouseListener(this);
addMouseMotionListener(this);
// test!
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent ke){
int c = ke.getKeyCode();
if(c == 'P'){
Bezier bzr = (Bezier)curve.get(point_num);
System.out.println("{");
for(int i = 0; i< bzr.getPoints(); i++ )
System.out.println(""+bzr.getX(i)+", "+bzr.getY(i));
System.out.println("},");
}else if(c == 'O'){
System.out.println("{");
for(int j=0;j0){ // 制御点の描画
offg.setColor(Color.red);
Bezier bzr = (Bezier)curve.get(point_num);
for(int i = 0; i < bzr.getPoints(); i++ ) {
Point p = bzr.getPoint(i) ;
offg.fillRect(p.x-3, p.y-3, 7, 7);
offg.drawString(Integer.toString(i+1), p.x-3, p.y-6);
}
}
for(int i = 0; i < curve.size() ; i++){ // 曲線描画
Bezier bzr = (Bezier)curve.get(i);
if(capture_mode_FLG && point_num==i && mode==M_MOD )
bzr.drawBezier(offg, Color.blue ,-1);
else
bzr.drawBezier(offg, null, -1);
}
if(mode==M_MOD && cooFlg){ // draw coordinate
Bezier bzr = (Bezier)curve.get(point_num);
offg.setColor(Color.black);
for(int i=0;i0 ){
p = (Point)que.remove(0);
backi.setRGB(p.x,p.y,nc);
check[p.y][p.x] = false;
if(p.x0)
if( offi.getRGB(p.x,p.y-1)==oldc)
if( check[p.y-1][p.x]){
q = new Point(p.x,p.y-1);
check[q.y][q.x] = false;
que.add(q); }
if(p.x>0)
if( offi.getRGB(p.x-1,p.y)==oldc )
if( check[p.y][p.x-1] ){
q = new Point(p.x-1,p.y);
check[q.y][q.x] = false;
que.add(q); }
}
}
// ------- Lister -------------
public void mouseDragged(MouseEvent ev){
if( mode == M_MOD ){ //modify
if(captured_point == -1) return;
Bezier bzr = (Bezier)curve.get(point_num);
bzr.setLocation(captured_point, ev.getX(), ev.getY() );
repaint();
}else if(mode == M_DRW){ //draw
if( pen_x == -1 ){
pen_x = ev.getX();
pen_y = ev.getY();
}else{
double m;
backg.setColor( pen_c );
m = (double)(ev.getY()-pen_y)/(double)(ev.getX()-pen_x);
if( -1 < m && m < 1 )
for(int mm=-pen_breadth;mm<=pen_breadth;mm++)
backg.drawLine(ev.getX(),ev.getY()+mm,pen_x,pen_y+mm);
else
for(int mm=-pen_breadth;mm<=pen_breadth;mm++)
backg.drawLine(ev.getX()+mm,ev.getY(),pen_x+mm,pen_y);
pen_x = ev.getX();
pen_y = ev.getY();
repaint();
}
}
}
public void mouseMoved(MouseEvent ev){}
public void mouseClicked(MouseEvent ev){
System.out.println("Click"+mode
+"("+ev.getX()+","+ev.getY()+")");
if(mode==M_ADD){//add
if(newBzrP==0){
newBzr = new Bezier();
newBzr.setBreadth( pen_breadth );
newBzr.setColor( pen_c );
newBzr.add(ev.getX(),ev.getY());
newBzrP++;
}else if(++newBzrP= mx &&
bzr.getY(i)-3 <= my &&
bzr.getY(i)+3 >= my)
break;
}
if(i < bzr.getPoints() ) captured_point = i;
repaint();
}
}
public void mouseReleased(MouseEvent ev){
if( mode==M_MOD ){// modify
captured_point = -1;
}else if(mode == M_DRW){ // pen
pen_x=-1; pen_y=-1;
}
}
}
class Bezier{
public Vector points = new Vector();
public static final short MAX_POINTS = 7;
//private short pointcount = 0;
private Color mycolor;
private int breadth;
public Bezier(){
//System.out.println("Bezier Constractor");
mycolor = Color.black;
breadth=0;
}
public void setColor(Color c){ mycolor = c; }
public Color getColor(){ return mycolor; }
public void setBreadth(int BRD){ breadth = BRD; }
public int getBreadth(){ return breadth; }
public int getX(int index){//indexの点のX座標を返す
return ((Point)points.get(index)).x;
}
public int getY(int index){//indexの点のY座標を返す
return ((Point)points.get(index)).y;
}
public Point getPoint(int index){//indexの点を返す
return (Point)points.get(index);
}
/* public int size(){
return points.size();
}*/
public int getPoints(){ // 保持点の数
return points.size();
//return pointcount;
}
public void setLocation( int index, int x,int y ){//indexの点の座標を修正
Point p = getPoint(index);
p.x = x;
p.y = y;
points.set(index, p);
}
public void add(int x,int y){//その点を加える
Point p = new Point(x,y);
add(p);
}
public void add(Point p){
//if( pointcount < MAX_POINTS ){
if( points.size() < MAX_POINTS ){
//pointcount++;
points.add(p);
}
}
public void remove(int index){
if( 0 <= index && index < points.size() )
points.remove(index);
}
public void drawBezier(Graphics g, Color clr ,int brd ) // 曲線描画
{ //サンプルよりほぼそのまま引用
int i, j;
double x1, x2, y1, y2;
double bernstein[] = new double[points.size()];
Point p = (Point)points.get(0);
Color color;
int brdth;
if( clr == null ){ color = mycolor ; }
else {color = clr; }
if( brd < 0 ){ brdth = breadth; }
else { brdth = brd; }
x1 = p.x; y1 = p.y;
g.setColor(color);
for(double t = 0; t <= 1; t += 0.01){
for(i = 0; i < points.size(); i++){ // bernstein関数を計算
bernstein[i] = (double)kaijyo(points.size()-1)
/ (kaijyo(i)*kaijyo(points.size()-1-i));
for(j = 1; j <= i; j++) bernstein[i] *= t;
for(j = 1; j <= points.size()-1-i; j++) bernstein[i] *= (1-t);
}
x2 = y2 = 0;
for(i = 0; i < points.size(); i++){
p = (Point)points.get(i);
x2 += p.x * bernstein[i];
y2 += p.y * bernstein[i];
}
double m;
m = (y1-y2)/(x1-x2);
if( -1 < m && m < 1 )
for(int mm=-brdth;mm<=brdth;mm++)
g.drawLine((int)x1,(int)(y1+mm),(int)x2,(int)(y2+mm));
else
for(int mm=-brdth;mm<=brdth;mm++)
g.drawLine((int)(x1+mm),(int)y1,(int)(x2+mm),(int)y2);
//g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
x1 = x2; y1 = y2;
}
}
private int kaijyo(int num){ // 階乗を計算
int total = 1;
if(num == 0) return 1;
for(; num > 1; num--) total *= num;
return total;
}
}