import java.awt.event.*; import java.awt.*; import java.applet.*; import java.util.*; class Obi { int haba2; //帯の幅の2乗 int haba; //帯の幅 int edamotox;int edamotoy; //基本枝の枝元のx、y int edasakix;int edasakiy; //基本枝の枝先のx、y int tuuka_kaisuu; //最近接距離を求めるときの通過回数記録 int enx;int eny; //円領域の中心のx、y int tyokkei ; //円領域の直径 boolean moto_saki_tadasii; //基本枝の枝元と枝先が正しく設定されたかを示すフラグ boolean enryouiki; /*円領域かどうかの判定用フラグ*/ String buimeisyou; /*部位の名前(頭とか尾など)*/ } public class orio3 extends Applet implements Runnable, MouseListener, MouseMotionListener, ActionListener{ Thread myTh; public void run() { while(true){ try {myTh.sleep(100);} catch (InterruptedException e) {break;} enzu_saitekika(); } } // public void start() {myTh = new Thread(this);myTh.start();} // public void stop() {myTh = null;} int posx0;int posy0; int posx1;int posy1; int vposx0;int vposy0; int vposx1;int vposy1; //基本枝の平行移動時のベクトル Label lbel; int i; //上部文字表示用ラベル boolean sinki = true; //基本枝によって加えた帯が新規なら真 boolean hajinoten = true; //基本枝の棒の端の点を選択したなら真 boolean heikouidou = true; //基本枝の棒の平行移動をする状態なら真 int sagyouJyoutai; //作業状態 1基本枝−基本枝、2基本枝−円図、3円図−円図、4円図−展開図、5展開図−展開図 int r=7; //基本枝構造の直線の両端の円の半径 int enzurasi_x=450; //円図のx軸方向のオフセット値 int enzurasi_y=200; int edaUgosasuIti=0; //枝の動く部分 0=枝元、1=枝先 //最近接距離制限用の変数の定義 int sai_kinsetu_kyori_seigen_zensuu; //最近接距離制限の全数 int sai_kinsetu_kyori_kumi_i[] = new int[500]; //最近接距離制限の組の片方iの帯番号 int sai_kinsetu_kyori_kumi_j[] = new int[500]; //最近接距離制限の組の片方jの帯番号 int sai_kinsetu_kyori[]= new int[500] ; //最近接距離 //円図の最適化に用いる変数の定義 int zenenergy; //円図の全エネルギー int enzu_haba =500; //円図の正方形用紙の幅 int hyouji_haba=300; //円図の画面上の表示の幅 int zenene_old,zenene_new; // //帯領域用変数の定義 int nobis; //帯領域の数 int activeobi; //活性な帯の番号 Obi obis[] = new Obi[500]; //帯領域のインスタンス定義 //円図最適化 void enzu_saitekika(){ //int zenene_old,x_old,y_old,zenene_new; int x_old,y_old; int syoki_ondo=200000;//初期温度 int saisyuu_ondo=1000;//最終温度 int cycle_suu=500;//サイクル数 for (int i=1; i<=cycle_suu; i++ ){ for (int obibangou=1; obibangou<=nobis; obibangou++ ){ if(obis[obibangou].enryouiki){ zenene_old= zenenergy_keisan(); x_old=obis[obibangou].enx; y_old=obis[obibangou].eny; obis[obibangou].enx=obis[obibangou].enx +(int)(3*Math.random())-1; obis[obibangou].eny=obis[obibangou].eny +(int)(3*Math.random())-1; zenene_new=zenenergy_keisan(); int tempre;//温度の定義 tempre=(saisyuu_ondo-syoki_ondo)*(i-1)/(cycle_suu-1)+cycle_suu; if( tempre==0){ tempre=1;} tempre=1000; if(metro(zenene_old,zenene_new,tempre)==0){ obis[obibangou].enx=x_old; obis[obibangou].eny=y_old; } } } } repaint(); } //メトロポリス法による判定 int metro(int ene_old,int ene_new,int tempr) { int mflag; double ran1; double einput,exdel; mflag=0; if(ene_old>=ene_new){mflag=1; } if(ene_old< ene_new){ ran1= Math.random(); einput=-(double)(ene_new-ene_old)*1000/tempr; if (einput>=88.0) {einput=88.0;} exdel=Math.exp(einput); if (exdel>=ran1) {mflag=1;} } return mflag; } //円図の全エネルギーの算出 int zenenergy_keisan(){ int zenene;int addene,dd;//ddは最近接距離と実際の距離の差 zenene=0; for (int bangou=1; bangou <= sai_kinsetu_kyori_seigen_zensuu; bangou++ ){ dd= (intkyori( obis[ sai_kinsetu_kyori_kumi_i[bangou]].enx, obis[ sai_kinsetu_kyori_kumi_i[bangou]].eny, obis[ sai_kinsetu_kyori_kumi_j[bangou]].enx, obis[ sai_kinsetu_kyori_kumi_j[bangou]].eny) - sai_kinsetu_kyori[bangou] ); addene=0; if( dd<0){addene=5*dd* dd-10;} if( (0<=dd)&&(dd<10)){addene=dd-10;} if(10<=dd){addene=0;} zenene=zenene+ addene ; } //円図の幅を求める enzu_haba=0; for (int obibangou=1; obibangou<=nobis; obibangou++ ){ if(obis[obibangou].enryouiki){ if( Math.abs(obis[obibangou].enx) >enzu_haba) { enzu_haba=Math.abs(obis[obibangou].enx) ;} if( Math.abs(obis[obibangou].eny) >enzu_haba) { enzu_haba=Math.abs(obis[obibangou].eny) ;} } } enzu_haba=enzu_haba*2; zenene=zenene+ enzu_haba*7; //円領域が用紙辺上に位置することのエネルギー見積もり addene=0; for (int obibangou=1; obibangou<=nobis; obibangou++ ){ if(obis[obibangou].enryouiki){ addene=addene+ intmin ( Math.abs (Math.abs (obis[obibangou].enx)-enzu_haba/2) , Math.abs (Math.abs (obis[obibangou].eny)-enzu_haba/2) ); } } zenene=zenene+addene; return zenene; } //最近接距離制限の制定 void sai_kinsetu_kyori_seigen_seitei(){ int sai_kinsetu_kyori_seigen_bangou ; //最近接距離制限の通し番号 int x_genzaiti,y_genzaiti; int idou_obi_bangou; //移動する帯の番号 boolean moto_ni_iru; //現在位置が枝元にいる場合は真、逆の場合は偽 boolean keizoku; //真なら、継続する sai_kinsetu_kyori_seigen_bangou =0 ; for (int iboi=1; iboi<=nobis-1; iboi++ ){ for (int jboi=iboi+1; jboi<=nobis; jboi++ ){ if( (obis[iboi].enryouiki)&&(obis[jboi].enryouiki) ){ sai_kinsetu_kyori_seigen_bangou =sai_kinsetu_kyori_seigen_bangou +1 ; sai_kinsetu_kyori_kumi_i[sai_kinsetu_kyori_seigen_bangou] = iboi; sai_kinsetu_kyori_kumi_j[sai_kinsetu_kyori_seigen_bangou] = jboi; //最近接距離を計算するのに用いるパラメータの初期化 sai_kinsetu_kyori[sai_kinsetu_kyori_seigen_bangou]=obis[iboi].haba; x_genzaiti=obis[iboi].edamotox; y_genzaiti=obis[iboi].edamotoy; for (int k=1; k<=nobis; k++ ){obis[k].tuuka_kaisuu=0;} obis[iboi].tuuka_kaisuu=1; idou_obi_bangou=iboi; moto_ni_iru=true; keizoku=true; //最近接距離を求める計算を実行 for (int m=1;keizoku;m++){ //移動する帯番号idou_obi_bangouを求める for (int k=1; k<=nobis; k++ ){ if( (intkyori(obis[k].edasakix ,obis[k].edasakiy, x_genzaiti,y_genzaiti )100){keizoku=false;} }//for(m)を受ける } } } sai_kinsetu_kyori_seigen_zensuu = sai_kinsetu_kyori_seigen_bangou; } //帯領域が円領域かどうかの判定 void enryouikihantei(){ for (int iboi=1; iboi<=nobis; iboi++ ){ obis[iboi].enryouiki=true; for (int jboi=1; jboi<=nobis; jboi++ ){ if(iboi!=jboi){ if(r>intkyori(obis[iboi].edasakix,obis[iboi].edasakiy,obis[jboi].edamotox,obis[jboi].edamotoy)){ obis[iboi].enryouiki=false; } } } } } //マウスボタンを押した場所の帯番号の取得 void obiBangouHantei(int bhx , int bhy){ sinki =true ; hajinoten = true; heikouidou = false; for (int bhi=1; bhi<=nobis; bhi++ ){ if( //平行移動を行うべきか判断 ((obis[bhi].edamotox-bhx)*(obis[bhi].edamotox-bhx)+(obis[bhi].edamotoy-bhy)*(obis[bhi].edamotoy-bhy) 円図"); KihonsiEnzuButton.addActionListener(this); pnl.add(KihonsiEnzuButton); add("South",pnl); nobis=1;addObi(150,150,150,200); activeobi=1;addObiatosyori() ; /* posx0=e.getX();posy0=e.getY(); posx1=e.getX();posy1=e.getY(); obiBangouHantei(posx0,posy0); enryouikihantei(); repaint();*/ sagyouJyoutai=1; } public void destroy() {removeMouseListener(this);} //マウス操作(ボタンを離したとき) public void mouseReleased(MouseEvent e) { addObiatosyori() ; edaSettei(); enryouikihantei(); sai_kinsetu_kyori_seigen_seitei(); repaint(); } //マウス操作(ボタンを押したとき) public void mousePressed(MouseEvent e) { posx0=e.getX();posy0=e.getY(); posx1=e.getX();posy1=e.getY(); obiBangouHantei(posx0,posy0); repaint(); } //マウス操作(ボタンをクリックしたとき) public void mouseClicked(MouseEvent e) { } //何もしない //マウス操作(カーソルが有効領域内に入ったとき) public void mouseEntered(MouseEvent e) { } //何もしない //マウス操作(カーソルが有効領域外に出たとき) public void mouseExited(MouseEvent e) { } //何もしない //マウス操作(ドラッグしたとき) public void mouseDragged(MouseEvent e) { if(!heikouidou){ if(edaUgosasuIti==0){//枝元を変更 obis[activeobi].edamotox =e.getX(); obis[activeobi].edamotoy =e.getY(); } if(edaUgosasuIti==1){//枝先を変更 obis[activeobi].edasakix =e.getX(); obis[activeobi].edasakiy =e.getY(); } obis[activeobi].haba2 = (obis[activeobi].edamotox-obis[activeobi].edasakix) *(obis[activeobi].edamotox-obis[activeobi].edasakix) +(obis[activeobi].edamotoy-obis[activeobi].edasakiy) *(obis[activeobi].edamotoy-obis[activeobi].edasakiy) ; obis[activeobi].haba=(int)Math.sqrt((float)obis[activeobi].haba2); } if(heikouidou){ obis[activeobi].edamotox =e.getX()+vposx0; obis[activeobi].edamotoy =e.getY()+vposy0; obis[activeobi].edasakix =e.getX()+vposx1; obis[activeobi].edasakiy =e.getY()+vposy1; } for (int obibangou=1; obibangou<=nobis; obibangou++ ){//枝の位置から円領域の位置を出す obis[obibangou].enx=(obis[obibangou].edamotox+obis[obibangou].edasakix)/2 -150; obis[obibangou].eny=(obis[obibangou].edamotoy+obis[obibangou].edasakiy)/2 -175; } repaint(); } public void mouseMoved(MouseEvent e) {} //ペイント public void paint(Graphics g) { String c=new String(); if ( sagyouJyoutai==1){lbel.setText(c.valueOf(activeobi)); } if ( sagyouJyoutai==2){lbel.setText(c.valueOf(zenene_old)); } //基本枝の描画 g.setColor(Color.black); for (int obibangou=1; obibangou<=nobis; obibangou++ ){ g.drawLine( obis[obibangou].edamotox, obis[obibangou].edamotoy, obis[obibangou].edasakix, obis[obibangou].edasakiy); //直線 g.drawOval(obis[obibangou].edamotox-r/2,obis[obibangou].edamotoy-r/2,r,r); //円 g.drawOval(obis[obibangou].edasakix-r/2,obis[obibangou].edasakiy-r/2,r,r); //円 } g.drawRect(300,50,300,300);//円図用の四角形の描画 //円領域の描画 g.setColor(Color.red); for (int obibangou=1; obibangou<=nobis; obibangou++ ){ if(obis[obibangou].enryouiki){ g.drawOval( ( obis[obibangou].enx-obis[obibangou].haba) * hyouji_haba/enzu_haba +enzurasi_x , ( obis[obibangou].eny-obis[obibangou].haba ) * hyouji_haba/enzu_haba +enzurasi_y , ( 2*obis[obibangou].haba ) * hyouji_haba/enzu_haba , ( 2*obis[obibangou].haba ) * hyouji_haba/enzu_haba ); //円 g.drawOval( (obis[obibangou].enx-r/2)*hyouji_haba/enzu_haba+enzurasi_x, (obis[obibangou].eny-r/4)*hyouji_haba/enzu_haba +enzurasi_y, r/2,r/2); //円 } } //最近接制限のある円領域の中心間に直線を描く g.setColor(Color.blue); for (int bangou=1; bangou <= sai_kinsetu_kyori_seigen_zensuu; bangou++ ){ g.drawLine( obis[ sai_kinsetu_kyori_kumi_i[bangou]].enx * hyouji_haba/enzu_haba +enzurasi_x, obis[ sai_kinsetu_kyori_kumi_i[bangou]].eny * hyouji_haba/enzu_haba +enzurasi_y , obis[ sai_kinsetu_kyori_kumi_j[bangou]].enx * hyouji_haba/enzu_haba +enzurasi_x, obis[ sai_kinsetu_kyori_kumi_j[bangou]].eny * hyouji_haba/enzu_haba +enzurasi_y ); //直線 } } //ボタンを押されたときの処理 public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("基本枝の入力")) { lbel.setText("きほんし から きほんし" ); sagyouJyoutai=1; // myTh = null;myTh.stop(); stop();スレッドの止め方イマイチ不明 } if(e.getActionCommand().equals("基本枝―>円図")){ lbel.setText("きほんし から えんず" ); sagyouJyoutai=2; edaSettei(); enSyokiIti(); sai_kinsetu_kyori_seigen_seitei(); // enzu_saitekika(); myTh = new Thread(this);myTh.start();//円図最適化のスレッド実行 } repaint(); } //枝先と枝元を正しく設定 void edaSettei() { //obis[0].moto_saki_tadasii=true; //moto_saki_tadasiiの真偽の初期化 for (int obibangou=1; obibangou<=nobis; obibangou++ ){ obis[obibangou].moto_saki_tadasii=false; } obis[1].moto_saki_tadasii=true; //実際の判定 for (int i=1; i<=nobis; i++ ){ for (int sansyou_obibangou=1; sansyou_obibangou<=nobis; sansyou_obibangou++ ){ if(obis[sansyou_obibangou].moto_saki_tadasii) for (int hanteisuru_obibangou=2; hanteisuru_obibangou<=nobis; hanteisuru_obibangou++ ){ if((sansyou_obibangou!= hanteisuru_obibangou)&&(!obis[hanteisuru_obibangou].moto_saki_tadasii)) { //もともと枝元先が正しい場合 if(intkyori( obis[sansyou_obibangou].edamotox, obis[sansyou_obibangou].edamotoy, obis[hanteisuru_obibangou].edamotox,obis[hanteisuru_obibangou].edamotoy)b){min=b ;} return min; } //2つの整数の最大値 int intmax(int a,int b){ int max; max=a; if(a