天天看點

二叉樹遞歸分形,牛頓分形圖案

1. 牛頓分形(newton fractal)

在複數域上使用牛頓疊代生成分形圖像,函數公式f(z) = z^3 – 1在複數域上面有

三個根,一個是1,另外兩個分别是複數-0.5+0.87i 與 -0.5 – 0.87i根據計算出來根

的值不同轉換為rgb三種不同的顔色,根據疊代次數的多少設定顔色值的大小,

即顔色強度。

二叉樹遞歸分形,牛頓分形圖案

2. 曼德布羅特集合分形(mandelbort set fractal) 使用複數函數公式f(z) = z^2 + c其中

c是一個複數

二叉樹遞歸分形,牛頓分形圖案

3. 遞歸分形樹 (recursion tree)– 類似二叉樹的遞歸生成樹幹,同時不斷的縮小樹幹長

度,根據遞歸次數不同與角度不同可以得到不同的遞歸分形樹,注意java最大棧

深度是64,過度的歸次數可能導緻java棧溢出錯誤。遞歸次數建議不要超過32.

二叉樹遞歸分形,牛頓分形圖案

根據角度不同,可以生成不同的二叉遞歸樹。

牛頓疊代與曼德爾波特分形算法需要複數範圍内的加減乘除計算,請先google一下

然後就知道啦。本人實作的複數計算的類如下:

package com.gloomyfish.fractal;  

public class complex  

{  

  private float real;  

  private float imaginary;  

  public complex(float paramfloat1, float paramfloat2)  

  {  

    this.real = paramfloat1;  

    this.imaginary = paramfloat2;  

  }  

  public float real()  

    return this.real;  

  public float imaginary()  

    return this.imaginary;  

  public float modulus()  

    return (float)math.sqrt(this.real * this.real + this.imaginary * this.imaginary);  

  public boolean equal(complex paramcomplex)  

    return ((this.real == paramcomplex.real()) && (this.imaginary == paramcomplex.imaginary()));  

  public complex add(complex paramcomplex)  

    return new complex(this.real + paramcomplex.real(), this.imaginary + paramcomplex.imaginary());  

  public complex subtract(complex paramcomplex)  

    return new complex(this.real - paramcomplex.real(), this.imaginary - paramcomplex.imaginary());  

  public complex multiply(complex paramcomplex)  

    return new complex(this.real * paramcomplex.real() - (this.imaginary * paramcomplex.imaginary()), this.real * paramcomplex.imaginary() + this.imaginary * paramcomplex.real());  

  public complex divide(complex paramcomplex)  

    float f1 = paramcomplex.real() * paramcomplex.real() + paramcomplex.imaginary() * paramcomplex.imaginary();  

    float f2 = (this.real * paramcomplex.real() + this.imaginary * paramcomplex.imaginary()) / f1;  

    float f3 = (this.imaginary * paramcomplex.real() - (this.real * paramcomplex.imaginary())) / f1;  

    return new complex(f2, f3);  

  public string tostring()  

    string str = (this.imaginary >= 0.0f) ? "+" : "-";  

    return this.real + str + math.abs(this.imaginary) + "i";  

}  

牛頓分形的算法代碼如下:

public class newtonfractal extends fractal {  

    private static final complex one = new complex(1.0f, 0.0f);  

    private static final complex three = new complex(3.0f, 0.0f);  

    public newtonfractal(int widthimage, int heightimage) {  

        super(widthimage, heightimage);  

        // default start point and end point  

        // primary group,   

        this.x1 = -1.0f;  

        this.y1 = -1.0f;  

        this.x2 = 1.0f;  

        this.y2 = 1.0f;  

        // second group  

        //  this.x1 = -3.0f;  

        //  this.y1 = -1.76f;  

        //  this.x2 = 3.0f;  

        //  this.y2 = 1.76f;  

        // end comment  

    }  

    @override  

    public void buildfractal() {  

        int[] inpixels = new int[getwidth()*getheight()];  

        getrgb(fractalimage, 0, 0, getwidth(), getheight(), inpixels );  

        int index = 0;  

        float xdelta = ((x2 - x1) / (float)width);  

        float ydelta = ((y2 - y1) / (float)height);  

        for(int row=0; row<height; row++) {  

            int ta = 0, tr = 0, tg = 0, tb = 0;  

            for(int col=0; col<width; col++) {  

                complex localcomplex2;  

                float f1 = this.x1 + col * xdelta;  

                float f2 = this.y2 - (row * ydelta);  

                complex localcomplex1 = new complex(f1, f2);  

                int k = 0;  

                do {  

                  complex localcomplex3 = localcomplex1.multiply(localcomplex1);  

                  complex localcomplex4 = localcomplex3.multiply(localcomplex1);  

                  localcomplex2 = localcomplex1;  

                  localcomplex1 = localcomplex1.subtract(localcomplex4.subtract(one).divide(three.multiply(localcomplex3)));  

                }  

                while ((++k < max_iters) && (!(localcomplex1.equal(localcomplex2))));  

                int l = 20 * k % 10; // keep value scope between 0 and 255  

                // if root is 1 then  

                if (localcomplex1.real() > 0.0f)  

                {  

                    tr = tg = l;  

                    tb = 255;  

                // if root is second complex = -0.5+0.87i  

                else if (localcomplex1.imaginary() > 0.0f)  

                    tr = tb = l;  

                    tg = 255;  

                else  

                  tr = 255;  

                  tg = tb = l;  

                index = row * width + col;  

                ta = 255;  

                inpixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  

            }  

        }  

        setrgb(fractalimage, 0, 0, getwidth(), getheight(), inpixels);  

曼德爾波特分形算法如下:

public class mandelbrotsetfractal extends fractal {  

    private float delta = 0.01f;  

    public mandelbrotsetfractal(int widthimage, int heightimage) {  

        this.delta = 0.01f;  

        this.x1 = (-(this.width / 2) * this.delta);  

        this.y1 = (-(this.height / 2) * this.delta);  

        this.x2 = (-this.x1);  

        this.y2 = (-this.y1);  

            float f1 = y2 - (row * delta);  

                float f5;  

                int i1;  

                float f2 = x1 + col * delta;  

                complex localcomplex1 = new complex(f2, f1);  

                complex localcomplex2 = new complex(0.0f, 0.0f);  

                int l = 0;  

                do  

                  localcomplex2 = localcomplex2.multiply(localcomplex2).add(localcomplex1);  

                  f5 = localcomplex2.modulus();  

                  k = (f5 > 2.0f) ? 1 : 0; }  

                while ((++l < 32) && (k == 0));  

                if (k != 0) {  

                  i1 = 255 - (255 * l / 32);  

                  i1 = math.min(i1, 240);  

                  tr = tg = tb = i1;  

                  i1 = (int)(100.0f * f5) / 2 + 1;  

                  int i2 = 101 * i1 & 0xff;  

                  int i3 = 149 * i1 & 0xff;  

                  int i4 = 199 * i1 & 0xff;  

                  tr = i2;  

                  tg = i3;  

                  tb = i4;  

遞歸分形樹代碼如下:

import java.awt.borderlayout;  

import java.awt.color;  

import java.awt.dimension;  

import java.awt.font;  

import java.awt.fontformatexception;  

import java.awt.graphics;  

import java.awt.graphics2d;  

import java.awt.renderinghints;  

import java.io.ioexception;  

import java.io.inputstream;  

import java.util.date;  

import javax.swing.jcomponent;  

import javax.swing.jframe;  

public class fractaltree extends jcomponent {  

    /** 

     *  

     */  

    private static final long serialversionuid = 8812325148970066491l;  

    private int maxrecursions = 8; //never make this too big or it'll take forever  

    private double angle = 0.2 * math.pi; //angle in radians  

    private double shrink = 1.8; //relative size of new branches  

    public fractaltree() {  

        super();  

    protected void paintcomponent(graphics g) {  

        graphics2d g2 = (graphics2d) g;  

        g2.setrenderinghint(renderinghints.key_antialiasing, renderinghints.value_antialias_on);  

        g2.setpaint(color.white);  

        g2.fillrect(0, 0, 400, 400);  

        rendertree(g2);  

        g2.setpaint(color.red);  

        try {  

            g2.setfont(loadfont());  

        } catch (fontformatexception e) {  

            // todo auto-generated catch block  

            e.printstacktrace();  

        } catch (ioexception e) {  

        g2.drawstring("created by gloomyfish " + new date(system.currenttimemillis()), 10, 320);  

     * create fractal tree using recursion 

     * @param graphics2d g2 

    private void rendertree(graphics2d g2) {  

        g2.setpaint(new color(128, 96, 64));  

        recursion(400.0d / 2.0d, 400.0d -1.0d, 0.0d, -1.0d, 400.0d / 2.3d, 0, g2);  

    // http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche31.html  

    void recursion(double posx, double posy, double dirx, double diry, double size, int n, graphics2d g2)  

    {  

        int x1, x2, y1, y2;  

        x1 = (int)posx;  

        y1 = (int)posy;  

        x2 = (int)(posx + size * dirx);  

        y2 = (int)(posy + size * diry);  

        g2.drawline(x1, y1, x2, y2);  

        if(n >= maxrecursions) return;  

        double posx2, posy2, dirx2, diry2, size2;  

        int n2;  

        // calculate the new start point coordinate  

        posx2 = posx + size * dirx;  

        posy2 = posy + size * diry;  

        size2 = size / shrink; // make different length of line.  

        n2 = n + 1;  

        // rotate angle and get the new directx, directy  

        // http://www.jimloy.com/geometry/trigz.htm  

        // sin(theta + angle) = sin(theta) * cos(angle) + cos(theta) * sin(angle)  

        // cos(theta + angle) = -sin(angle) * sin(theta) + cos(theta) * cos(angle)  

        dirx2 = math.cos(angle) * dirx + math.sin(angle) * diry;  

        diry2 = -math.sin(angle) * dirx + math.cos(angle) * diry;  

        recursion(posx2, posy2, dirx2, diry2, size2, n2, g2);  

        dirx2 = math.cos(-angle) * dirx + math.sin(-angle) * diry;  

        diry2 = -math.sin(-angle) * dirx + math.cos(-angle) * diry;  

     * http://en.wikipedia.org/wiki/mandelbrot_set 

     * http://www.urbanfonts.com/fonts/sans-serif-fonts.htm 

     * @return 

     * @throws fontformatexception 

     * @throws ioexception 

    public font loadfont() throws fontformatexception, ioexception{  

        string fontfilename = "amersn.ttf";  

        inputstream is = this.getclass().getresourceasstream(fontfilename);  

        font actionjson = font.createfont(font.truetype_font, is);  

        font actionjsonbase = actionjson.derivefont(font.bold, 12);  

        return actionjsonbase;  

    public static void main(string[] args) {  

        jframe frame = new jframe("fractal tree ui - gloomyfish");  

        frame.setdefaultcloseoperation(jframe.exit_on_close);  

        frame.getcontentpane().setlayout(new borderlayout());  

        // display the window.  

        frame.getcontentpane().add(new fractaltree(), borderlayout.center);  

        frame.setpreferredsize(new dimension(450,400));  

        frame.pack();  

        frame.setvisible(true);