[分形]DLA团簇模型的摸拟
EmilMatthew(EmilMatthew@126.com)
1前言:
DLA团簇模型是分形成长中的一个很易于实现的模型.(当然啦,背后的理论工作是非常高有难度的,涉及到代数,泛函分析,非线性偏微分方程等知识。我们就拿着别人的研究出的成果,来感受一下其中的美妙吧J)
团簇模型最初是80年代初T.A.Witten和L.M.Sander在研究悬浮在溶液或大气中的金属粉末,煤灰和烟尘等微粒的无规扩散凝聚过程中得出的研究成果.
2DLA模型的摸拟规则:
a在某个规定好大小的画布的中心处O随机的产生少量粒子.
b在以中心O为圆心,以Rmax为半径的圆周的周围(比Rmax稍大,如Rmax+d处)
随机的生成新的粒子。新粒子随即进行随机的游走------上下左右四个方向。
如果游走至原来粒子的附近(即一个已吸收粒子的上下左右的任何一个方位),则该粒子认为被吸收。
如果游戏的粒子走出了距离中心点2*Rmax的距离,则删去这个粒子.
c当产生粒子数少于规定的最大粒子数时,则重复b.
采用5000个粒子总数,画布大小为400*400的模拟效果如下:
3程序整体设计:
While(test particle num<require num)
{
Init a new particle ar Rmax+d circle’s side;
While(particle is not restored or particle is not out of 2*Rmax)
{
Next pos selection;
Particle move to next step;
Detect whether particle is near the bound of the particles which have been stored.
{
If(“yes”)
Update the map matrix , particle restored.
}
}
}
4关键代码:
4.1新粒子是否被吸引的算法:
这里,关于如何判定粒子被吸引的算法值得一提:
关于粒子在图上的分布情况,可以用一个二维矩阵进行存储.
矩阵上的每个位置的取值与画布上的各个像素一一对应,一共可以取三个值UNDRAWED , READY , DRAWED分别表示该点的状况是未着点,边界点,已着点.
对于某个确认新吸收的粒子,设其位置坐标为(curX,curY),则其周围的粒子的值的情况可以用下面这个判定来改变:
if(infoMatrix[curX-1][curY]!=DRAWED)
infoMatrix[curX-1][curY]=READY;
if(infoMatrix[curX][curY-1]!=DRAWED)
infoMatrix[curX][curY-1]=READY;
if(infoMatrix[curX+1][curY]!=DRAWED)
infoMatrix[curX+1][curY]=READY;
if(infoMatrix[curX][curY+1]!=DRAWED)
infoMatrix[curX][curY+1]=READY;
这样的话,对于以后生成的新粒子是否已处于被吸收的位置的判定,只需要用一句:
if(infoMatrix[curX][curY]==READY&&在界内)
即可,判定是否被吸收算法的复杂度被控制在常数级.
4.2模拟程序代码:
void DLATest(long maxNum,int width,int height,HDC inHDC)
{
long curNum=0;
int centerX,centerY;
int curX,curY;
int i,j;
long drawColor=34048;
int rMax,d;
float pi;
int** infoMatrix;
bool flag;
float nextPos;
centerX=width/2;centerY=height/2;
/*mem apply*/
infoMatrix=(int**)malloc(sizeof(int*)*height);
for(i=0;i<height;i++)
infoMatrix[i]=(int*)malloc(sizeof(int)*width);
/*map matrix init*/
for(j=0;j<width;j++)
for(i=0;i<height;i++)
infoMatrix[i][j]=UNDRAWED;
/*produce the init particles*/
srand((unsigned int)time (NULL));
i=0;
while(i<10)
{
curX=centerX+(int)eRandom(10);
curY=centerY+(int)eRandom(10);
SetPixel(inHDC,curX,curY,drawColor);
infoMatrix[curX][curY]=DRAWED;
if(infoMatrix[curX-1][curY]!=DRAWED)
infoMatrix[curX-1][curY]=READY;
if(infoMatrix[curX][curY-1]!=DRAWED)
infoMatrix[curX][curY-1]=READY;
if(infoMatrix[curX+1][curY]!=DRAWED)
infoMatrix[curX+1][curY]=READY;
if(infoMatrix[curX][curY+1]!=DRAWED)
infoMatrix[curX][curY+1]=READY;
i++;
}
curNum=0;
rMax=75;
d=10;
pi=3.14159;
while(curNum<maxNum)
{
curX=centerX+(rMax+d)*cos(eRandom(180)/pi);
curY=centerY+(rMax+d)*sin(eRandom(180)/pi);
i=0;
flag=false;
while(!flag&&i<20000)
{
nextPos=eRandom(100);
if(nextPos<25)//left
curX--;
else if(nextPos<50)//up
curY--;
else if(nextPos<75)//right
curX++;
else
curY++;
if(curX<=0||curX>=width||curY<=0||curY>=height)
break;
if(infoMatrix[curX][curY]==READY&&(curX-centerX)*(curX-centerX)+(curY-centerY)*(curY-centerY)<=rMax*rMax)
{
SetPixel(inHDC,curX,curY,drawColor);
infoMatrix[curX][curY]=DRAWED;
if(infoMatrix[curX-1][curY]!=DRAWED)
infoMatrix[curX-1][curY]=READY;
if(infoMatrix[curX][curY-1]!=DRAWED)
infoMatrix[curX][curY-1]=READY;
if(infoMatrix[curX+1][curY]!=DRAWED)
infoMatrix[curX+1][curY]=READY;
if(infoMatrix[curX][curY+1]!=DRAWED)
infoMatrix[curX][curY+1]=READY;
flag=true;
}
i++;
}
curNum++;
}
}
完成日:06/03/29
附录:
1测试程序下载:
http://emilmatthew.51.net/EmilPapers/06_12DLA/code.rar
若直接点击无法下载(或浏览),请将下载(或浏览)的超链接粘接至浏览器地( 推荐MYIE或GREENBORWSER)址栏后按回车.若不出意外,此时应能下载.