コンピュータグラフィックス

Mandelbrot set


[注意] 本年度の授業ではこの課題を提出する必要はありません。


マンデルブロ集合 (Mandelbrot set)は以下のように定義できます。

    複素数の数列 {zi} が
    z0 = 0,
    zn+1 = zn2 - c
       (n = 0,1,2,...)
    で定義されているとき、有界である (n→∞ で |zn|が発散しない)ような複素数 c の集合

この集合は複素平面上で非常に複雑な形をしていて、どんなに拡大しても 非常に入り組んだ形が見られます。黒い部分が マンデルブロ集合で、 それ以外の色はその点と Mandelbrot集合との「近さ」を表しています。 (下左図の全景は xmin=-0.9, xmax=2.1, ymin=-1.2, ymax=1.2で見られます)。

さて、指定したx,yの範囲内の点(x,y)について、 マンデルブロ集合に含まれているかどうかを 調べて表示するプログラムを考えましょう。

ここでは、ウィンドウ画面に表示できる範囲は 0≤wx≤width-1, 0≤wy≤height-1 を満たす点 (wx,wy) になります。 これが指定したx,yの範囲である

xmin ≤ x ≤ xmax,  ymin ≤ y ≤ ymax
を動くためには、次のような対応関係を満たす必要があります。
    wx=0   → x=xmin
    wx=width-1 → x=xmax
    wy=0   → y=ymin
    wy=height-1 → y=ymax
したがって画面上の点 (wx,wy) から、それに相当する複素平面上の点 z=x+iyを求めるには以下の式を使います。
    x=(xmax-xmin)*wx/(width-1) + xmin;
    y=(ymax-ymin)*wy/(height-1) + ymin;

zn+1zn2 - c
を計算しますが、|z|>2 ならば発散することが知られています。 また無限回数繰り返すことはできないので、最初に与えた値(ここでは 255*scale回)の間発散せずに計算を繰り返すことができたら そこで計算を打ち切ります。 戻ってきた値をscaleで割って0〜255のグレースケールとして表示しています。

次のフローチャートで示されるメソッド mandel() を定義しましょう。





コンピュータグラフィックス 演習


作成したプログラムが正しく動作することを確認したら、それぞれの 提出先に提出しなさい。

提出した後は、正しく提出されていることを http://nw.tsuda.ac.jp/class/algoB/local/handin/ で必ず確認しておいて下さい。

課題提出〆切は次回の講義が始まる時刻です。

課題2: マンデルブロ集合を描画する

提出ファイルMandelbrot.java
コメント欄:なし
提出先: 「宿題提出Web:コンピュータグラフィックス:課題2」 http://nw.tsuda.ac.jp/class/cg/local/handin/up.php?id=kadai2

マンデブロ集合を描画するプログラムを作成せよ。

Mandelbrot.javaの実装例
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;

public class Mandelbrot extends ToyGraphics {
    public Mandelbrot() { this(640,480); }
    public Mandelbrot(int w,int h) { super(w,h); }
    public static void main(String[] args) {
	Mandelbrot m = new Mandelbrot();
	m.run();
    };
    int mandel(double x,double y,int count) {

	// [課題] ここに適切なJavaのコードを書きなさい。

	return(count);
    }
    double xmin = -0.9;
    double xmax = 2.1;
    double ymin = -1.2;
    double ymax = 1.2;
    double wx2x(int wx) { return xmin + (xmax - xmin) * wx / (width - 1); }
    double wy2y(int wy) { return ymin + (ymax - ymin) * wy / (height - 1); }
    public void drawMandel() {
	int scale=16;
	for (int wy=0; wy < height; wy++) {
	    double y = wy2y(wy);
	    for (int wx=0; wx < width; wx++) {
		double x = wx2x(wx);
		int n = mandel(x,y,255*scale);
		setRGB(wx,wy,n/scale,n/scale,n/scale);
	    }
	}
	repaint(0,0,width,height);
    }
    public void run() { drawMandel(); }
    double px, py, rx, ry;
    public void mousePressed(MouseEvent e) {
	System.out.println("mouseReleased:("+e.getX()+","+e.getY()+")"+e.getButton());
	px = wx2x(e.getX());
	py = wy2y(e.getY());
    }
    public void mouseReleased(MouseEvent e) {
	System.out.println("mouseReleased:("+e.getX()+","+e.getY()+")"+e.getButton());
	rx = wx2x(e.getX());
	ry = wy2y(e.getY());
	xmax = Math.max(px,rx);
	xmin = Math.min(px,rx);
	ymax = Math.max(py,ry);
	ymin = Math.min(py,ry);
	drawMandel();
    }
}