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