分享
 
 
 

分形学习之LS文法构图

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

如果昨天的递归分形算法画出的图案好象不那么有技术含量,那么今天的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<State> s = new Stack<State>();

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<State>();

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;

}

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有