[简介]
最近一直在读《深奥的简洁》,里面有一章介绍了几种使用噪声产生分形图的方法,感觉很有意思,于是尝试使用计算机模拟了一下,效果还不错(噪声法比传统迭代法在编程上好实现一些,后来发现这类算法还不少,搜索chaosgame可以找到更多)。
[sierpinski三角形的噪声产生法]
在这些噪声游戏中,sierpinski(谢尔宾斯基)三角形的生成规则可谓是最简单的:
1.在平面上选取三个点,标记为1、2、3,作为大三角形的顶点。
2.选择其中一点,作为“当前点”(比如选择1号)。
3.产生1~3的随机数,在该数表达的顶点与“当前点”的中点绘制一个新点,并将新点作为“当前点”。
4.重复步骤3,即可逼近图案。
*.注意随机数最好不要使用以时间作为种子的产生方式。
[模拟程序]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package com.geiv.chaos;
import java.awt.event.keyevent;
import com.thrblock.util.randomset;
import geivcore.defaultfactor;
import geivcore.keyfactor;
import geivcore.keylistener;
import geivcore.r;
import geivcore.uesi;
import geivcore.enginedata.obj.obj;
public class sierpinski extends defaultfactor implements keylistener{
uesi ues;
obj[] basepoint;
obj crtpoint;
public sierpinski(uesi ues, int times){
this .ues = ues;
basepoint = new obj[ 3 ];
//创建三个基准点
for ( int i = 0 ;i < 3 ;i++){
basepoint[i] = ues.creatobj(uesi.bgindex);
basepoint[i].addglpoint( "70dbdb" , 0 , 0 );
basepoint[i].show();
}
basepoint[ 0 ].setcentralx( 400 );
//设置三点位置
basepoint[ 0 ].setcentraly( 60 );
basepoint[ 1 ].setcentralx( 60 );
basepoint[ 1 ].setcentraly( 550 );
basepoint[ 2 ].setcentralx( 740 );
basepoint[ 2 ].setcentraly( 550 );
crtpoint = basepoint[ 0 ];
//将0号点作为当前点
this .setkeylistener( this );
ues.pushkeyboardio( this );
for ( int i = 0 ;i < times;i++){
generatenew();
}
}
@override
public void dokeybord(keyfactor whom, int keycode, boolean ispressed) {
//挂载回调
if (ispressed){
if (keycode == keyevent.vk_space){
//空格对应创建一个新点
generatenew();
} else if (keycode == keyevent.vk_a){
//a对应创建100个新点
for ( int i = 0 ;i < 100 ;i++){
generatenew();
}
} else if (keycode == keyevent.vk_b){
//b对应创建1000个新点
for ( int i = 0 ;i < 1000 ;i++){
generatenew();
}
}
}
}
public void generatenew(){
obj flagpoint = basepoint[randomset.getrandomnum( 0 , 2 )];
//随机选择基准点之一
float nx = (flagpoint.getcentralx() + crtpoint.getcentralx())/2f;
//计算中点
float ny = (flagpoint.getcentraly() + crtpoint.getcentraly())/2f;
obj newpoint = ues.creatobj(uesi.bgindex);
//创建新点
newpoint.addglpoint( "70dbdb" , 0 , 0 );
newpoint.setcolor(randomset.getrandomcoldcolor());
newpoint.setcentralx(nx);
//设置坐标
newpoint.setcentraly(ny);
newpoint.show();
crtpoint = newpoint;
//置为当前点
}
public static void main(string[] args) {
uesi ues = new r();
new sierpinski(ues, 0 );
//后面的构造参数可以设置初始点数。
}
}
|
[模拟结果]
在b键按下时
[barnsleyfern的噪声产生法]
相比于sierpinski三角的简单规则性,barnsleyfern(分形羊齿草)给人以更加复杂的印象,出于它的复杂性,混沌学科经常拿出它来证明“简单规则也可产生复杂对象”的结论。
它的产生规则也不是很复杂:
1.首先给定”当前点”(0,0),我们用ox,oy表示横纵坐标。
2.计算下一点(nx,ny)需要以一定随机规则选择下列四种迭代公式之一:
1)以%1的概率选择此迭代公式:
nx=0;
ny=0.16f*oy;
2)以%85的概率选择此迭代公式:
nx=0.85*ox+0.04*oy;
ny=-0.04*ox+0.85*oy+1.6;
3)以%7的概率选择此迭代公式:
nx=0.2*ox-0.26*oy;
ny=0.23*ox+0.22*oy+1.6;
4)以%7的概率选择此迭代公式:
nx=-0.15*ox+0.28*oy;
ny=0.26*ox+0.24*oy+0.44;
3.绘制(nx,ny),并将其设为当前点,重复2,即可无限逼近结果。
↑以上公式摘自wiki:http://en.wikipedia.org/wiki/barnsley_fern。在编程时,我发现一个问题,wiki并未指明这个坐标的决对值与屏幕大小的关系,也并未说明x、y轴的方向,在我自己定义的坐标系下绘制总是不成功,后来我按照公式搜索,找到了这个面:http://people.sc.fsu.edu/~jburkardt/cpp_src/fern_opengl/fern.cpp。这是一个c++下的opengl程序,而里面用了与wiki相同的公式,也就是说,这组公式是以opengl的坐标系为基准的,在做了对应变换后终于成功绘制。
[模拟程序]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
package com.geiv.chaos;
import geivcore.defaultfactor;
import geivcore.keyfactor;
import geivcore.keylistener;
import geivcore.r;
import geivcore.uesi;
import geivcore.enginedata.obj.obj;
import java.awt.color;
import java.awt.event.keyevent;
import com.thrblock.util.randomset;
public class barnsleyfern extends defaultfactor implements keylistener{
uesi ues;
obj crtpoint;
public barnsleyfern(uesi ues, int times){
this .ues = ues;
crtpoint = ues.creatobj(uesi.bgindex);
crtpoint.addglpoint( "70dbdb" , 0 , 0 );
crtpoint.show();
crtpoint.setcentralx( 0 );
crtpoint.setcentraly( 0 );
ues.setviewoffsetx( 90 );
this .setkeylistener( this );
ues.pushkeyboardio( this );
for ( int i = 0 ;i < times;i++){
generatenew();
}
}
@override
public void dokeybord(keyfactor whom, int keycode, boolean ispressed) {
//键盘io的方式同上例
if (ispressed){
if (keycode == keyevent.vk_space){
generatenew();
} else if (keycode == keyevent.vk_a){
for ( int i = 0 ;i < 100 ;i++){
generatenew();
}
} else if (keycode == keyevent.vk_b){
for ( int i = 0 ;i < 1000 ;i++){
generatenew();
}
}
}
}
public void generatenew(){
float nx,ny;
float ox = crtpoint.getcentralx()/150f,oy = ( 600 - crtpoint.getcentraly())/60f;
//这里做了opengl坐标转换,在设置新点位置时对应反转。
double code = 100.0 * randomset.getrandomfloatin_1();
//随机浮点数数0~100
if (code >= 0 &&code <= 1 ){
nx = 0 ;
ny = 0 .00f * ox + 0 .16f * oy;
} else if (code > 1 && code <= 86 ){
nx = 0 .85f*ox + 0 .04f*oy;
ny = - 0 .04f*ox + 0 .85f*oy + 1 .6f;
} else if (code > 86 && code <= 93 ){
nx = 0 .2f*ox - 0 .26f*oy;
ny = 0 .23f*ox + 0 .22f*oy + 1 .6f;
} else {
nx = - 0 .15f*ox + 0 .28f*oy;
ny = 0 .26f*ox + 0 .24f*oy + 0 .44f;
}
obj newpoint = ues.creatobj(uesi.bgindex);
newpoint.addglpoint( "70dbdb" , 0 , 0 );
newpoint.setcolor(color.green);
newpoint.setcentralx(nx*150f);
//将之前的坐标变换抵消
newpoint.setcentraly( 600 - ny*60f);
newpoint.show();
crtpoint = newpoint;
//设置新点为当前点。
}
public static void main(string[] args) {
uesi ues = new r();
new barnsleyfern(ues, 0 );
}
}
|
[模拟结果]
总结
以上就是本文关于java chaos game噪声游戏实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/shuzhe66/article/details/40113149