Java—混沌分形
- 一、迭代函数系统(IFS)
- 1.IFS枫叶
- 2.IFS叶
- 3.IFS树及IFS雪花
- 二、谢尔宾斯基分形
- 1.谢尔宾斯基三角形
- 2.谢尔宾斯基地毯
提示:本文数据来源:paulbourke.net
一、迭代函数系统(IFS)
IFS以仿射变换为框架,根据几何对象的整体与局部具有自相似的结构,将总体形状以一定的概率按不同的仿射变换迭代下去,直至得到满意的分形图形。
1.IFS枫叶
IFS方程如下:
xn+1 = a xn + b yn + e
yn+1 = c xn + d yn + f
set 1 | set 2 | set 3 | set 4 | |
---|---|---|---|---|
a | 0.1400 | 0.4300 | 0.4500 | 0.4900 |
b | 0.0100 | 0.5200 | -0.4900 | 0.0000 |
c | 0.0000 | -0.4500 | 0.4700 | 0.0000 |
d | 0.5100 | 0.5000 | 0.4700 | 0.5100 |
e | -0.0800 | 1.4900 | -1.6200 | 0.0200 |
f | -1.3100 | -0.7500 | -0.7400 | 1.6200 |
代码实现:
public void drawIFS() {
double [] a={ 0.1400 , 0.4300 , 0.4500 , 0.4900};
double [] b={ 0.0100 , 0.5200 , -0.4900 , 0.0000};
double [] c={ 0.0000 , -0.4500 , 0.4700 , 0.0000};
double [] d={ 0.5100 , 0.5000 , 0.4700 , 0.5100};
double [] e={-0.0800 , 1.4900 , -1.6200 , 0.0200};
double [] f={-1.3100 , -0.7500 , -0.7400 , 1.6200};
double x=0,y=0;
for (int i = 0; i < 5000000; i++) {
int j = random.nextInt(4);
double tempX = a[j]*x + b[j]*y + e[j];
double tempY = c[j]*x + d[j]*y + f[j];
int px = (int) (tempX * 100 + 800);
int py = (int) (tempY * 100 + 400);
gr.drawLine(px, 800-py, px, 800-py);
x = tempX;
y = tempY;
}
}
2.IFS叶
IFS方程如下:
xn+1 = a xn + b yn + e
yn+1 = c xn + d yn + f
set 1 | set 2 | set 3 | set 4 | |
---|---|---|---|---|
a | 0.0000 | 0.7248 | 0.1583 | 0.3386 |
b | 0.2439 | 0.0337 | -0.1297 | 0.3694 |
c | 0.0000 | -0.0253 | 0.3550 | 0.2227 |
d | 0.3053 | 0.7426 | 0.3676 | -0.0756 |
e | 0.0000 | 0.2060 | 0.1383 | 0.0679 |
f | 0.0000 | 0.2538 | 0.1750 | 0.0826 |
代码实现:
public void drawIFS() {
double [] a={ 0.0000 , 0.7248, 0.1583, 0.3386};
double [] b={ 0.2439 , 0.0337, -0.1297, 0.3694};
double [] c={ 0.0000 , -0.0253, 0.3550, 0.2227};
double [] d={ 0.3053 , 0.7426, 0.3676,-0.0756};
double [] e={ 0.0000 , 0.2060, 0.1383, 0.0679};
double [] f={ 0.0000 , 0.2538, 0.1750, 0.0826};
double x=0,y=0;
for (int i = 0; i < 10000000; i++) {
int j = random.nextInt(4);
double tempX = a[j]*x + b[j]*y + e[j];
double tempY = c[j]*x + d[j]*y + f[j];
int px = (int) (tempX * 700 + 500);
int py = (int) (tempY * 700 + 100);
gr.drawLine(px, 800-py, px, 800-py);
x = tempX;
y = tempY;
}
}
3.IFS树及IFS雪花
IFS方程如下:
xn+1 = a xn + b yn + e
yn+1 = c xn + d yn + f
set 1 | set 2 | set 3 | set 4 | set 5 | set 6 | set 7 | |
---|---|---|---|---|---|---|---|
a | 0.0500 | -0.0500 | 0.0300 | -0.0300 | 0.5600 | 0.1900 | -0.3300 |
b | 0.0000 | 0.0000 | -0.1400 | 0.1400 | 0.4400 | 0.0700 | -0.3400 |
c | 0.0000 | 0.0000 | 0.0000 | 0.0000 | -0.3700 | -0.1000 | -0.3300 |
d | 0.4000 | -0.4000 | 0.2600 | -0.2600 | 0.5100 | 0.1500 | 0.3400 |
e | -0.0600 | -0.0600 | -0.1600 | -0.1600 | 0.3000 | -0.2000 | -0.5400 |
f | -0.4700 | -0.4700 | -0.0100 | -0.0100 | 0.1500 | 0.2800 | 0.3900 |
IFS方程如下:
xn+1 = a xn + b yn + e
yn+1 = c xn + d yn + f
set 1 | set 2 | set 3 | set 4 | set 5 | set 6 | |
---|---|---|---|---|---|---|
a | 0.38200 | 0.11800 | 0.11800 | -0.30900 | -0.30900 | 0.38200 |
b | 0.00000 | -0.36330 | 0.36330 | -0.22450 | 0.22450 | 0.00000 |
c | 0.00000 | 0.36330 | -0.36330 | 0.22450 | -0.22450 | 0.00000 |
d | 0.38200 | 0.11800 | 0.11800 | -0.30900 | -0.30900 | -0.38200 |
e | 0.30900 | 0.36330 | 0.51870 | 0.60700 | 0.70160 | 0.30900 |
f | 0.57000 | 0.33060 | 0.69400 | 0.30900 | 0.53350 | 0.67700 |
二、谢尔宾斯基分形
相较于IFS的多次循环,谢尔宾斯基分形则是通过递归实现的
1.谢尔宾斯基三角形
分形构造,平面称谢尔宾斯基三角形,立体称希尔宾斯基金字塔。
根据自相似特性,希尔宾斯基三角形是由三个尺寸减半的谢尔宾斯基三角形按照品字形叠加而成。
代码实现:
public void Sierpinski(int x1,int y1,int x2,int y2,int x3,int y3) {
if(Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))<=40) {
Polygon p = new Polygon();
p.addPoint(x1, y1);
p.addPoint(x2, y2);
p.addPoint(x3, y3);
gr.fillPolygon(p);
return;
}
int x_1 = (x1+x2)/2;
int y_1 = (y1+y2)/2;
int x_2 = (x1+x3)/2;
int y_2 = (y1+y3)/2;
int x_3 = (x3+x2)/2;
int y_3 = (y3+y2)/2;
//递归调用
Sierpinski(x1,y1,x_1,y_1,x_2,y_2);
Sierpinski(x_1,y_1,x2,y2,x_3,y_3);
Sierpinski(x_2,y_2,x_3,y_3,x3,y3);
}
2.谢尔宾斯基地毯
谢尔宾斯基地毯的构造与谢尔宾斯基三角形相似,区别仅在于谢尔宾斯基地毯是以正方形而非等边三角形为基础的。将一个实心正方形划分为的9个小正方形,去掉中间的小正方形,再对余下的小正方形重复这一操作便能得到谢尔宾斯基地毯。
代码实现:
public void Sierpinski(int x1,int y1,int x2,int y2) {
gr.drawRect(x1,y1,Math.abs(x2-x1),Math.abs(y2-y1));//画出地毯的边框
Sierpinski_1(x1,y1,x2,y2);
}
public void Sierpinski_1(int x1,int y1,int x2,int y2) {
if((x2-x1)<10) {
return;
}
int x_1 = x1 + (x2 - x1)/3;
int y_1 = y1 + (y2 - y1)/3;
int x_2 = x1 + (x2 - x1)*2/3;
int y_2 = y1 + (y2 - y1)*2/3;
Polygon p = new Polygon();
p.addPoint(x_1, y_1);
p.addPoint(x_2, y_1);
p.addPoint(x_2, y_2);
p.addPoint(x_1, y_2);
gr.fillPolygon(p);
//递归调用
Sierpinski_1(x1,y1,x_1,y_1);
Sierpinski_1(x_2,y1,x2,y_1);
Sierpinski_1(x_1,y1,x_2,y_1);
Sierpinski_1(x1,y_1,x_1,y_2);
Sierpinski_1(x_2,y_1,x2,y_2);
Sierpinski_1(x1,y_2,x_1,y2);
Sierpinski_1(x_1,y_2,x_2,y2);
Sierpinski_1(x_2,y_2,x2,y2);
}