特別付録 Javaで描く自己相似図形



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

/*
    class Affine means:
    x'= xx * x + xy * y + xo
    y'= yx * x + yy * y + yo
*/

class Affine {
    double xx, xy, xo;
    double yx, yy, yo;

    /* constructor */
    /* make a unit matrix */ 
    Affine() {
	xx = 1.0;
	yy = 1.0;
    }
 
    void scale(double a) {
	xx *= a;
	xy *= a;
	xo *= a;
	yx *= a;
	yy *= a;
	yo *= a;
    }

    void scale(double a, double b) {
	xx *= a;
	xy *= a;
	xo *= a;
	yx *= b;
	yy *= b;
	yo *= b;
    }

    void shift(double a, double b) {
	xo += a;
	yo += b;
    }

    void rotate(double theta) {
	double ct = Math.cos(theta);
	double st = Math.sin(theta);

	double Nxx = xx * ct - yx * st;
	double Nxy = xy * ct - yy * st;
	double Nxo = xo * ct - yo * st;
	double Nyx = yx * ct + xx * st;
	double Nyy = yy * ct + xy * st;
	double Nyo = yo * ct + xo * st;

        xo = Nxo;
	xx = Nxx;
	xy = Nxy;
	yo = Nyo;
	yx = Nyx;
	yy = Nyy;
    }

    void mult(Affine m) {
	double Nxx = xx * m.xx + yx * m.xy ;
	double Nxy = xy * m.xx + yy * m.xy ;
	double Nxo = xo * m.xx + yo * m.xy  + m.xo;
	double Nyx = xx * m.yx + yx * m.yy ;
	double Nyy = xy * m.yx + yy * m.yy ;
	double Nyo = xo * m.yx + yo * m.yy  + m.yo;

	xx = Nxx;
	xy = Nxy;
	xo = Nxo;
	yx = Nyx;
	yy = Nyy;
	yo = Nyo;
    }

    double det(){
        return xx*yy-xy*yx;
    }
    
}
class coordinate{
   double x,y;
  static final double left=-0.5;
  static final double right=1.5;
  static final double bottom=-1;
  static final double top=1;
 

  void transformed(coordinate p, Affine m){
	    x = p.x * m.xx + p.y * m.xy +  m.xo;
	    y = p.x * m.yx + p.y * m.yy +  m.yo;
   }
   void map(int w[]){
            w[0]=(int)Math.round(256*(x-left)/(right-left));
            w[1]=(int)Math.round(256*(y-top)/(bottom-top));
   } 
}

public class levy extends Applet{
    Affine f1,f2;
    static final coordinate origin= new coordinate();
 
   public void init(){

     setBackground(Color.white);

     f1=new Affine();
     f1.scale(1,-1);
     f1.rotate(Math.PI / 4);
     f1.scale(Math.sqrt(0.5));
     f2=new Affine();
     f2.shift(-1.0, 0.0);
     f2.rotate(Math.PI / 4);
     f2.scale(Math.sqrt(0.5));
     f2.shift(1.0, 0.0);

  }

   public void paint(Graphics g){
     Affine t=new Affine();
     trans(0,t,g);
  }
   
   public void trans(int n, Affine t, Graphics g){    
     if (n==14) {
        int w[];
        w= new int[2];
        coordinate z = new coordinate();
        z.transformed(origin,t);
        z.map(w);
        g.drawLine(w[0],w[1],w[0],w[1]);
     }
     else {
        Affine m1= new Affine();
        m1.mult(f1);
        m1.mult(t);
        trans(n+1,m1,g);   
        Affine m2= new Affine();
        m2.mult(f2);
        m2.mult(t);
        trans(n+1,m2,g);
     };
   }
         
}


Class Affineは,行列演算のパッケージです。

Affine m = new Affine() で,mに恒等変換がセットされます。

Class coordinateは,物理座標と仮想座標との変換を担当します。

Class levyが本体です。

Affine f1に f1 =scale(1,-1)*rotate(π/4)*scale(1/√2)を,

Affine f2に f2 =shift(1,0)*rotate(π/4)*scale(1/√2)*shift(1,0)を

対応させています。

なお,実際に上で動いているアプレットは,安定な動作をするように修正したものになっています。参照


次に進む(colored Dragon)

Javaに関する情報は, 日本サン JAVAガイド