SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Javaで学ぶグラフィックス処理

ジュリア集合の色付けを工夫して芸術的なフラクタル図形を描く

マンデルブロー図形の一部をクリックしてジュリア図形を描く


  • X ポスト
  • このエントリーをはてなブックマークに追加

プログラム

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

   }

}

次のページ
プログラムの使い方

修正履歴

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Javaで学ぶグラフィックス処理連載記事一覧

もっと読む

この記事の著者

石立 喬(イシダテ タカシ)

1955年東京工大卒。同年、NECへ入社し、NEC初のコンピュータの開発に参画。磁気メモリ、半導体メモリの開発、LSI設計などを経て、1989年帝京大学理工学部教授。情報、通信、電子関係の教育を担当。2002年定年により退職し現在に至る。2000年より、Webサイト「Visual C++の勉強部屋」を公開。...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/310 2008/03/16 10:44

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング