プログラム
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class Julia extends Applet implements
ItemListener,ActionListener,MouseListener,MouseMotionListener{
int SIZE=200;
int MSIZE=200;
int X0=10,Y0=150;
int X1=X0+SIZE+20,Y1=150;
Choice choice1,choice2,choice3,choice4;
Label label1,label2,label3,label4,label5,
label6,label7,label8,label9;
Button button1,button2,button3,button4,button5;
TextField tfield1,tfield2,tfield3,tfield4,tfield5;
Image img_mandel;
//Cの実数部、Cの虚数部
double creal,cimag;
//Z0の実数部の中心、Z0の虚数部の中心、表示の範囲
double z0real,z0imag,width;
//同上のクリックによる変化分
double z0real_d,z0imag_d;
//繰返し回数の上限、カラー階調数、クリック倍率
int count_max,color_base,ratio;
int type; //着色方式
public class Complex{
double re,im; //実数部と虚数部
public Complex(){ //コンストラクタ
re=0.0;
im=0.0;
}
public Complex(double a, double b){ //コンストラクタ
re=a;
im=b;
}
public Complex add(Complex a){ //加算
return new Complex(this.re+a.re, this.im+a.im);
}
public Complex sqr(){ //二乗
return new Complex(
(this.re + this.im)*(this.re - this.im), 2 * this.re * this.im);
}
public double abs2(){ //絶対値の二乗
return this.re * this.re + this.im * this.im;
}
public double arg(){ //偏角(argument)
return Math.atan(this.im / this.re);
}
}
public void init(){
//------------------------ GUI関係準備 ------------------------
// 中略
//------------------------ 初期化設定 ------------------------
// 中略
//-------------------- Mandelbrot図形準備 --------------------
double value;
int count;
Complex c=new Complex();
int[] pixels=new int[MSIZE*MSIZE];
for(int x=-MSIZE/2;x<MSIZE/2;x++){
c.re=x*2.5/MSIZE-0.75;
for(int y=-MSIZE/2;y<MSIZE/2;y++){
c.im=y*2.5/MSIZE;
Complex z=new Complex();
count=0;
do{
z=z.sqr().add(c);
value=z.abs2();
count++;
if(count>64){
count=-1;
break;
}
} while(value<4.0);
Color color=countToColorA(count,32);
pixels[(y+MSIZE/2)*MSIZE+x+MSIZE/2]=color.getRGB();
}
}
img_mandel=createImage(
new MemoryImageSource(MSIZE,MSIZE,pixels,0,MSIZE));
}
// ----------------------- GUI関係メソッド -----------------------
//チョイスが変更になった場合のメソッド
public void itemStateChanged(ItemEvent ie){
//中略
}
//ボタンをクリックしたときのメソッド
public void actionPerformed(ActionEvent ae){
// 中略
}
public void mouseDragged(MouseEvent me){}
//マウスをクリックしたときのメソッド
public void mousePressed(MouseEvent me){
int x=me.getX();
int y=me.getY();
if(x>X0 && x<X0+SIZE && y>Y0 && y<Y0+SIZE){ //ジュリア画像内
z0real_d=(x-(X0+SIZE/2))*width/SIZE; //変化分を記憶させる
z0real+=z0real_d;
z0imag_d=(y-(Y0+SIZE/2))*width/SIZE; //変化分を記憶させる
z0imag-=z0imag_d;
width/=ratio;
tfield3.setText(String.valueOf((float)z0real));
tfield4.setText(String.valueOf((float)z0imag));
tfield5.setText(String.valueOf((float)width));
drawJulia();
}
//マンデルブロー画像内
if(x>X1 && x<X1+SIZE && y>Y1 && y<Y1+SIZE){
creal=(x-X1)*2.5/MSIZE-2.0;
cimag=-(y-Y1)*2.5/MSIZE+1.25;
tfield1.setText(String.valueOf((float)creal));
tfield2.setText(String.valueOf((float)cimag));
drawMandel();
drawJulia();
}
}
public void mouseMoved(MouseEvent me){}
public void mouseEntered(MouseEvent me){}
public void mouseExited(MouseEvent me){}
public void mouseClicked(MouseEvent me){}
public void mouseReleased(MouseEvent me){}
//数値をカラーに変換するメソッドA
private Color countToColorA(int count, int base){
int r,g,b;
if(count<0) return Color.black;
int d=(count % base)*256/base;
int m=(int)(d/42.667);
switch(m){
//青→シアン
case 0: r=0; g=6*d; b=255; break;
//シアン→緑
case 1: r=0; g=255; b=255-6*(d-43);break;
//緑→黄
case 2: r=6*(d-86); g=255; b=0; break;
//黄→赤
case 3: r=255; g=255-6*(d-129);b=0; break;
//赤→マゼンタ
case 4: r=255; g=0; b=6*(d-171); break;
//マゼンタ→青
case 5: r=255-6*(d-214); g=0; b=255; break;
default: r=0; g=0; b=0; break;
}
return new Color(r,g,b);
}
//数値をカラーに変換するメソッドB
private Color countToColorB(int count, int base){
int r,g,b;
if(count<0) return Color.black;
int d=(count % base)*256/base;
int m=d/32;
switch(m){
//青→マゼンタ
case 0: r=63+6*d; g=63; b=255; break;
//マゼンタ→白
case 1: r=255; g=63+6*(d-32); b=255; break;
//白→シアン
case 2: r=255-6*(d-64);g=255; b=255; break;
//シアン→緑
case 3: r=63; g=255; b=255-6*(d-96);break;
//緑→黄
case 4: r=63+6*(d-128);g=255; b=63; break;
//黄→赤
case 5: r=255; g=255-6*(d-160);b=63; break;
//赤→黒
case 6: r=255-6*(d-192);g=63; b=63; break;
//黒→青
case 7: r=63; g=63; b=63+6*(d-224);break;
default: r=0; g=0; b=0; break;
}
return new Color(r,g,b);
}
//ジュリア図形を描画するメソッド
private void drawJulia(){
Graphics g=getGraphics();
int count;
int x,y;
double zr,zi;
double value=0.0;
double step=width/SIZE;
Complex c=new Complex(creal,cimag);
Complex z=new Complex();
g.setColor(Color.black);
g.drawString("ジュリア図形描画中",X0+SIZE+20,Y0+300);
for(x=-SIZE/2;x<=SIZE/2;x++){
zr=x*step+z0real;
for(y=-SIZE/2;y<=SIZE/2;y++){
zi=y*step+z0imag;
z=new Complex(zr,zi);
count=0;
do{
z=z.sqr().add(c); //Julia集合の繰返し演算(Z=Z*Z+C)
value=z.abs2(); //絶対値(の二乗)の計算
count++;
if(count>count_max){ //発散しないと判断
count=-1;
break;
}
} while(value<4.0); //これを抜けると発散と判断
switch(type){ //着色の色を設定する
//繰返し回数そのままA
case 0:g.setColor(countToColorA(count,color_base));
break;
//繰返し回数そのままB
case 1:g.setColor(countToColorB(count,color_base));
break;
//繰返し回数の平方根
case 2:if(count>0)count=(int)Math.sqrt(count);
g.setColor(countToColorB(count,color_base));
break;
//発散時のZの偏角
case 3:if(count>0) count=
(int)((z.arg()/(2*Math.PI)+0.5)*255);
g.setColor(countToColorB(count,color_base));
break;
default:break;
}
g.drawLine(
X0+SIZE/2+x,Y0+SIZE/2-y,X0+SIZE/2+x,Y0+SIZE/2-y);
}
}
g.setColor(getBackground());
g.fillRect(X0+SIZE+10,Y0+280,130,30);
}
//マンデルブロー図形を描画するメソッド
public void drawMandel(){
Graphics g=getGraphics();
g.drawImage(img_mandel,X1,Y1,null);
//crealとcimagに応じて白丸を描く
g.setColor(Color.white);
int x=(int)((creal+2.0)*MSIZE/2.5);
int y=(int)((cimag-1.25)*MSIZE/2.5);
g.drawOval(X1+x-2,Y1-y-2,4,4);
}
public void paint(Graphics g){
drawMandel();
}
}