[分形几何,AS2]L系统编程的实现

[分形几何]L系统编程的实现.

                                                                                                           EmilMatthew

                                                                                                                       05/11/15

首先看一下用程序生成的KNOCH曲线,在迭代次数不同情况下的变化:

       http://bbs.flash8.net/bbs/UploadFile/2005-11/20051115132943209.swf 

       显然,你可以清楚的感觉到KNOCH曲线在面积上为0,在长度上不断扩大特性(在给定的尺度下有一个上限值)

       和这个Knoch曲线相类似的图形还有Sierpinski三角形

       如下:

http://bbs.flash8.net/bbs/UploadFile/2005-11/20051115132950548.swf

 

       那么,具体到程序上,这样的图形是如何绘制的呢,这类图形的绘制在分形几何上有个相关的领域,叫做L系统,这是一种基于字符串技术的绘制图形技术,就像LOGO语言那像,通过解释命令字符串,来控制画笔的移动:

       比如:

       F代表在当前的位置方向向前移动

       +从当前的方向向左转一个给定的角度.

       -从当前的方向向右转一个给定的角度.

      

      

       Knoch的生成命令为:(在一个叫做Fractint19.5L系统的软件上)

       Axiom F                ;初始状态,一根直线

       F=F+F—F+F     ;迭代法则,每次在前一次的命令字符串中的F用这个规则去替换.

      

       在达到规定的迭代次数后,便可以从字符串头部向后解释命令绘制出相应的图形.

       那么,具体到程序上,这样的迭代如何去实现呢.(这里我还没能力实现一个通用的解释程序,只谈最关键的迭代的实现)

       我认为一个比较好的相法是这样:

       设置两个队列(字符队列,每个队列结点上存放一个元字符)qA,qB

开始时:qA存放初始情况下的字符,qB为空.

I=1

Sign=’A’

While(i<迭代次数上限)

{

              if(Sign==’A’)

              {

                     qA中的字符逐个出队

                     {

                            如果遇到的是替换法则相对应的字符,则将替换法则中的字符逐个入队qB.

                            如果不是,则将当前qA中的出队字符直接入qB

}

}

 

              if(Sign==’B’)

              {

                     qB中的字符逐个出队

                     {

                            如果遇到的是替换法则相对应的字符,则将替换法则中的字符逐个入队qA.

                            如果不是,则将当前qB中的出队字符直接入q

}

}

       ißi+1

}

 

下面给出在AS2语言中这种算法的实现:

       for(i=0;i<_root.gInitString.length;i++)

                     queueA.enQueue(String(_root.gInitString.charAt(i)));

      

       i=0;

       sign=_root.SIGN_A;

      

       //Produce The Drawing String.

 

       while(i<_root.gIteratorLimit)

              {

                    

                     if(sign==_root.SIGN_A)

                     {     //queueA          to queueB

                            while(!queueA.isEmpty())

                            {

                                   tmpData=String(queueA.deQueue());

                                   if(tmpData=="F"||tmpData=="f"||tmpData=="G"||tmpData=="g")

                                          for(j=0;j<_root.gInitString.length;j++)

                                                 {

                                                        queueB.enQueue(_root.gInitString.charAt(j));

                                                 }

                                   else if(tmpData=="+"||tmpData=="-"||tmpData=="|")

                                                 queueB.enQueue(tmpData);

                            }

                            sign=_root.SIGN_B;

                     }    

                     else if(sign==_root.SIGN_B)

                     {

                            //queueB          to queueA

                            while(!queueB.isEmpty())

                            {

                                   tmpData=String(queueB.deQueue());

                    

                                   if(tmpData=="F"||tmpData=="f"||tmpData=="G"||tmpData=="g")

                                          for(j=0;j<_root.gInitString.length;j++)

                                                 queueA.enQueue(_root.gInitString.charAt(j));

                                   else if(tmpData=="+"||tmpData=="-"||tmpData=="|")

                                                 queueA.enQueue(tmpData);

                                  

                            }

                           

                            sign=_root.SIGN_A;

                     }

                     i++;

                    

              }

             

              //copy to drawCmdStr.

              drawCmdStr="";

              if (sign==_root.SIGN_A)

                     while(!queueA.isEmpty())

                            drawCmdStr+=String(queueA.deQueue());

              else

                     while(!queueB.isEmpty())

                            drawCmdStr+=String(queueB.deQueue());

             

       //The Core Draw Sub.  

       var myVector:E2DVector=new E2DVector(0,0);//the move cursor

       _root.gIteratorTimes=0;

       _root.gCmdLen=0;

       _root.gCurArc=0;

       _root.gIntervalID=setInterval(KochCurve,_root.gFps,myVector,drawCmdStr);

 

绘制的过程是简单的,就是一个根据字符串的命令不断更新画图位置的过程:

这是Koch曲线的绘制过程:

function KochCurve(inVector:E2DVector,inCmdDrawStr:String):Void

{

       var stepLen:Number=20;

       var i:Number=0;

       var tmpStr:String=new String();

                    

       while(i<stepLen&&_root.gCmdLen<inCmdDrawStr.length)

       {

              tmpStr=inCmdDrawStr.charAt(_root.gCmdLen);

                           

              if(tmpStr=="F")

              {

                     with(eval("_root.LBrush"))

                     {

                            lineStyle(1,_root.gColorArr[13],100);

                            moveTo(_root.gXOffset+inVector.x,_root.gYOffset+inVector.y);

                            inVector.plus2(_root.gStepLength*Math.cos(_root.gCurArc),_root.gStepLength*Math.sin(_root.gCurArc));

                            lineTo(_root.gXOffset+inVector.x,_root.gYOffset+inVector.y);

                            //     trace(inVector.toString());

                     }

              }

              else if(tmpStr=="+")

              {

                     _root.gCurArc+=_root.UnClkWiseArc;

                                   //inVector.rotate(_root.UnClkWiseArc);

              }

              else if(tmpStr=="-")

              {

                     _root.gCurArc+=_root.ClkWiseArc;

                                   //inVector.rotate(_root.ClkWiseArc);

              }

              else

              {

                     trace3("error cmd char parse!/n");

              }

                           

                     i++;

                     _root.gCmdLen++;

                     //trace(_root.gCmdLen);

       }    

                           

                           

       if(_root.gCmdLen==inCmdDrawStr.length)

              _root.clearInterval(_root.gIntervalID);

}

 

Knoch不同的是Sierpinksi三角形的命令中多了一个X,它的意思是,该字符只在迭代时有效,在具体绘图时,跳过不做即是.

源码下载:

http://emilmatthew.51.net/downloads/LSystem1.rar

http://emilmatthew.51.net/downloads/LSystem2.rar

//如果上面这个链接无法响应下载(有可能是被网站给屏蔽掉了),则可使用下载工具(如迅雷等)下载。欢迎提出批评与指正意见.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值