分形学习之LS文法构图

如果昨天的递归分形算法画出的图案好象不那么有技术含量,那么今天的LS文法构图算法就很有档次了!CQ今天弄出了这个东西后也是非常激动啊!

   好东西啊!要和大家分享!哈哈!

 首先来介绍一下LS文法,这是在美国生物学家Axxx Lxxx (名字太长,不好记!不过感谢他的发明!哈哈!) 发明的一种文法描述方法: graftal上逐渐发展起来的形式语言的一个重要分支.后来人们称之为L-system.

讲了些没有实际作用的历史,现在就进入正题!

LS文法是一类独特的迭代过程,他的核心思想就是重写.作为一种形式话的语言,LS文法用字母表和符号串来表达生成对象的初始形式,称为公理.然后根据一组产生式重写规则,将初始的每个字符依次替换为新的字符形式,反复进行,直到最后生成图形.

   在二维平面上,LS是这样工作的!

   首先讲符号:

F: 以当前方向前进,画线

f: 以当前方向前进,不画线

+:逆时针旋转 alpha

-:顺时针旋转 alpha

[:当前信息压栈

]:将上一个[处存的信息出栈

 

 

 

我们来看koch曲线的LS文法生成(不知道koch曲线吗!网上找找资料吧!分形入门的时候本来要贴的,忘记了!哈哈!)

w:    F      (初始的形态: 一条直线段)

alpha  60     (变化的角度)

P:    F-> F – F + + F – F (变化规则: 把一条直线段变成四个小直线段)

 

 

 

然后再进行LS文法生成:

Step 1 : F

Step 2 : F – F + + F – F

Step3 : F – F + + F – F –F – F + + F – F + + F – F + + F – F –F – F + + F – F

Setp4: …

就这样依次无限循环下去就得到了koch曲线的文法

文法有什么用呢?

当然有用,根据得到的这个文法串,我们就可以画图了!

根据这个规则来:

F: 以当前方向前进,画线

f: 以当前方向前进,不画线

+:逆时针旋转 alpha

-:顺时针旋转 alpha

[:当前信息压栈

]:将上一个[处存的信息出栈

我们可以写一个while+switch语句配合来很轻松的实现对文法串的分析:

贴个例子:假设要对一个picString进行分析就可以用以下代码实现

// picString进行分析,根据字符串指示信息画图

        int length = picString.length();

        for (int offset = 0; offset < length; offset++) {

            switch (picString.charAt(offset)) {

            case 'F':

                forwardLine();

                break;

            case 'f':

                forwardWithOutLine();

                break;

            case '+':

                antiRotate(alpha);

                break;

            case '-':

                rotate(alpha);

                break;

            case '[':

                saveState();

                break;

            case ']':

                loadState();

                break;

            }

        }

下面给出我今天的成果哦!

先贴运行效果:

第二张:

还没有染色,不过如果理解了算法的话很轻松就可以染色了!

如果把rule再变换,还可以出现更多的图形!

下面就把代码贴出:

 (开源积极分子J)

 

 

 

package fractalPanels;

 

 

 

/**

 * LS 文法生成的树

 * 支持单一规则

 */

import java.awt.Point;

import java.util.Stack;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.geom.AffineTransform;

 

 

 

public class TreePanel extends FractalPanel {

 //树的很多形态

 /**

  * F[-F]F[+F]F    25 向上 

  * FF+[+F-F-F]-[-F+F+F] 20 蓬松

  * F[+F]F[-F+F] 25 

  */

    private int alpha;

 

 

 

    private String rule;

 

 

 

    private int time;

 

 

 

    private String picString;

 

 

 

    private int currentAngle = 90; // 当前绘图方向

 

 

 

    private Stack s = new Stack();

 

 

 

    private Point currentPoint = new Point(300,500); // 当前画笔在的点

 

 

 

    private int length;

 

 

 

    // 字符串参数带F

    public TreePanel(String rule, int alpha, int time, int length) {

        this.rule = rule;

        this.alpha = alpha;

        this.time = time;

        this.length = length;

        this.picString = rule;

        initPic();

    }

 

 

 

    private void initPic() {

        for (int i = 0; i < time; i++) {

            LS();

        }

    }

 

 

 

    // 根据规则生成字符串

    private void LS() {

        picString = picString.replaceAll("F", rule);

    }

 

 

 

    public void draw() {

        //初始化

        currentAngle = 90;

        s = new Stack();

        currentPoint = new Point(300, 650);

       

        // picString进行分析,根据字符串指示信息画图

        int length = picString.length();

        for (int offset = 0; offset < length; offset++) {

            switch (picString.charAt(offset)) {

            case 'F':

                forwardLine();

                break;

            case 'f':

                forwardWithOutLine();

                break;

            case '+':

                antiRotate(alpha);

                break;

            case '-':

                rotate(alpha);

                break;

            case '[':

                saveState();

                break;

            case ']':

                loadState();

                break;

            }

        }

    }

 

 

 

    /***************************************************************************

     * 画图辅助函数 坐标系说明: (0,0)为左上角的点,angle是以水平向右为0

     **************************************************************************/

 

 

 

    /**

     * 根据递归层数向前画线

     */

    private void forwardLine() {

        Graphics g = getGraphics();

        int x = currentPoint.x;

        int y = currentPoint.y;

        int endX = (int)(x + length*Math.cos(currentAngle/180.0 * Math.PI));

        int endY = (int)(y - length*Math.sin(currentAngle/180.0 * Math.PI));

        g.drawLine(x,y,endX,endY);

        currentPoint.setLocation(endX,endY);

    }

 

 

 

    /**

     * 根据递归层树前进不画线

     */

    private void forwardWithOutLine() {

        int endX = (int)(currentPoint.x + length*Math.cos(currentAngle/180.0 * Math.PI));

        int endY = (int)(currentPoint.y - length*Math.sin(currentAngle/180.0 * Math.PI));

        currentPoint.setLocation(endX,endY);

    }

 

 

 

    /**

     * 顺时针旋转

     *

     * @param rotateAngle

     *            旋转角度

     */

    private void rotate(int rotateAngle) {

        currentAngle -= rotateAngle;

    }

 

 

 

    /**

     * 逆时针旋转

     *

     * @param rotateAngle

     *            旋转角度

     */

    private void antiRotate(int rotateAngle) {

        currentAngle += rotateAngle;

    }

 

 

 

    private void saveState() {

//        State state = new State(currentPoint, currentAngle);

        Point p = new Point();

        p.setLocation(currentPoint.x,currentPoint.y);

        State state = new State(p,currentAngle);

        s.push(state);

    }

 

 

 

    private void loadState() {

        State state = s.pop();

        currentPoint = state.position;

        currentAngle = state.angle;

    }

 

 

 

    /**

     * javaBean 存放当前画笔信息

     */

    private class State {

        int angle;

 

 

 

        Point position;

 

 

 

        State(Point currentPoint, int angle) {

            position = currentPoint;

            this.angle = angle;

        }

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(图形图象)