观察自然界中树的分叉,一根主干生长出两个侧干,每个侧干又长出两个侧干,以此类推,便生长出疏密有致的结构。这样的生长结构,使用递归算法可以模拟出来。

例如,分叉的侧干按45°的偏转角度进行生长的递归示意图如图1所示。

图1  生成树的递归示意图

按照树分叉生长侧干的递归思想,编写如下的HTML代码。

<!DOCTYPE html>

<head>

<title>递归分形树(一)</title>

</head>

<body>

<canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var maxdepth =4;

var curdepth = 0;

var alph=Math.PI/4;

function growtree()

{

ctx.translate(300,380);

branch(-Math.PI/2);

}

function branch(angle)

{

curdepth++;

ctx.save();

ctx.strokeStyle = "green";

ctx.lineWidth = 6;

ctx.rotate(angle);

ctx.beginPath();

ctx.moveTo(0,0);

ctx.lineTo(100,0);

ctx.stroke();

ctx.translate(100,0);

ctx.scale(0.75,0.75);

if(curdepth <= maxdepth)

{

branch(alph);

branch(-alph);

}

ctx.restore();

curdepth--;

}

growtree();

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出分叉树形,如图2所示。

图2  递归深度maxdepth =4,alph=45°的分叉树形

若将递归深度“maxdepth=4”修改为“maxdepth=12”,则在浏览器窗口中绘制出如图3所示的分叉树形。

图3  递归深度maxdepth =12,alph=45°的分叉树形

若将递归深度“maxdepth=4”修改为“maxdepth=10”,分叉偏转角度从45°(alph=Math.PI/4)修改为30°(alph=Math.PI/6),则在浏览器窗口中绘制出如,4所示的分叉树形。

 图4  递归深度maxdepth =10,alph=30°的分叉树形

由图3和图4可知,分叉的偏转角度不同,树形也会不同。实际上,自然界中树的侧干的生长不会按同一个角度进行分叉的,若将分叉的偏转角度取随机值,编写如下的HTML代码。

<!DOCTYPE html>

<head>

<title>递归分形树(二)</title>

</head>

<body>

<canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;"></canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var maxdepth =10;

var curdepth = 0;

function growtree()

{

ctx.translate(300,380);

branch(-Math.PI/2);

}

function branch(angle)

{

curdepth++;

ctx.save();

ctx.strokeStyle = "green";

ctx.lineWidth = 6;

ctx.rotate(angle);

ctx.beginPath();

ctx.moveTo(0,0);

ctx.lineTo(100,0);

ctx.stroke();

ctx.translate(100,0);

ctx.scale(0.75,0.75);

if(curdepth <= maxdepth)

{

branch(randomRange(0,Math.PI/4));

branch(randomRange(-Math.PI/4,0));

}

ctx.restore();

curdepth--;

}

function randomRange(min,max)

{

return Math.random()*(max-min) + min;

}

growtree();

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,在浏览器窗口中可能会绘制出如图5所示的分叉树形。

图5  分叉树形

不断地刷新浏览器窗口,可以随机绘制出不同的分叉树形,如图6所示。

图6   绘制出的不同分叉树形

如果将递归树形的生成元改为如图7所示的三分叉,即在上面HTML文件中的两行代码

branch(randomRange(0,Math.PI/4));

branch(randomRange(-Math.PI/4,0));

中间加上一行代码 branch(0);  再将递归深度“var maxdepth =10;”修改为“var maxdepth =6;”,则在浏览器窗口中可能会绘制出如图8所示的分叉树形。

图7  三分叉生成元

图8  三分叉递归树形

我们可以在树梢画一个红色小圆,表示树儿开花了,编写如下的HTML文件。

<!DOCTYPE html>

<head>

<title>递归分形树(三)</title>

</head>

<body>

<canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;"></canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var maxdepth =10;

var curdepth = 0;

function growtree()

{

ctx.translate(300,380);

branch(-Math.PI/2);

}

function branch(angle)

{

curdepth++;

ctx.save();

ctx.strokeStyle = "green";

ctx.lineWidth = 6;

ctx.rotate(angle);

ctx.beginPath();

ctx.moveTo(0,0);

ctx.lineTo(100,0);

ctx.stroke();

ctx.translate(100,0);

ctx.scale(0.75,0.75);

if(curdepth < maxdepth)

{

branch(randomRange(0,Math.PI/4));

branch(randomRange(-Math.PI/4,0));

}

if(curdepth == maxdepth)

{

ctx.fillStyle = '#ff0000';

ctx.beginPath();

ctx.arc(0,0,20,0,Math.PI*2,true);

ctx.fill();

}

ctx.restore();

curdepth--;

}

function randomRange(min,max)

{

return Math.random()*(max-min) + min;

}

growtree();

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,在浏览器窗口中可能会绘制出如图9所示的分叉树形。

图9  树梢开红花的分叉树形

不断地刷新浏览器窗口,可以随机绘制出不同的分叉树形,如图10所示。

图10  绘制出的不同树梢开红花的分叉树形

JavaScript图形实例:递归生成树的更多相关文章

  1. JavaScript图形实例:线段构图

    在“JavaScript图形实例:四瓣花型图案”和“JavaScript图形实例:蝴蝶结图案”中,我们绘制图形时,主要采用的方法是先根据给定的曲线参数方程计算出两点坐标,然后将两点用线段连接起来,线段 ...

  2. JavaScript图形实例:再谈IFS生成图形

    在“JavaScript图形实例:迭代函数系统生成图形”一文中,我们介绍了采用迭代函数系统(Iterated Function System,IFS)创建分形图案的一些实例.在该文中,仿射变换函数W的 ...

  3. JavaScript图形实例:随机SierPinski三角形

    在“JavaScript图形实例:SierPinski三角形”中,我们介绍了SierPinski三角形的基本绘制方法,在“JavaScript图形实例:迭代函数系统生成图形”一文中,介绍了采用IFS方 ...

  4. JavaScript图形实例:图形的旋转变换

    旋转变换:图形上的各点绕一固定点沿圆周路径作转动称为旋转变换.可用旋转角表示旋转量的大小. 旋转变换通常约定以逆时针方向为正方向.最简单的旋转变换是以坐标原点(0,0)为旋转中心,这时,平面上一点P( ...

  5. JavaScript图形实例:SierPinski三角形

    1.SierPinski三角形 Sierpinski三角形是一种分形,由波兰数学家谢尔宾斯基在1915年提出,它是一种典型的自相似集.其生成过程为: (1)取一个三角形(多数使用等边三角形): (2) ...

  6. JavaScript图形实例:Hilbert曲线

    德国数学家David Hilbert在1891年构造了一种曲线,首先把一个正方形等分成四个小正方形,依次从西北角的正方形中心出发往南到西南正方形中心,再往东到东南角的正方形中心,再往北到东北角正方形中 ...

  7. JavaScript图形实例:合成花卉图

    我们知道在直角坐标系中,圆的方程可描述为: X=R*COS(α) Y=R*SIN(α) 用循环依次取α值为0~2π,计算出X和Y,在canvas画布中将坐标点(X,Y)用线连起来,可绘制出一个圆.编写 ...

  8. JavaScript图形实例:四瓣花型图案

    设有坐标计算公式如下: X=L*(1+SIN(4α))*COS(α) Y=L*(1+SIN(4α))*SIN(α) 用循环依次取α值为0~2π,计算出X和Y,在canvas画布中对坐标位置(X,Y)描 ...

  9. JavaScript图形实例:图形的扇形变换和环形变换

    1.1  扇形变换 将如图1所示的上边长方形的图形变换为下边的扇形图形的变换称为扇形变换. 设长方形图形中任一点P1(X1,Y1)变换为扇形图形上的点P2(X2,Y2),长方形的长为X,扇形圆心坐标为 ...

随机推荐

  1. Java实现 蓝桥杯 图书排列(全排列)

    标题:图书排列 将编号为1~10的10本书排放在书架上,要求编号相邻的书不能放在相邻的位置. 请计算一共有多少种不同的排列方案. 注意,需要提交的是一个整数,不要填写任何多余的内容. 9 9 10 9 ...

  2. java实现排他平方数

    题目标题: 排它平方数 小明正看着 203879 这个数字发呆. 原来,203879 * 203879 = 41566646641 这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位 ...

  3. java实现第三届蓝桥杯机器人行走

    机器人行走 [编程题](满分18分) 某少年宫引进了一批机器人小车.可以接受预先输入的指令,按指令行动.小车的基本动作很简单,只有3种:左转(记为L),右转(记为R),向前走若干厘米(直接记数字). ...

  4. HttpUtil工具类,发送Get/Post请求,支持Http和Https协议

    HttpUtil工具类,发送Get/Post请求,支持Http和Https协议 使用用Httpclient封装的HttpUtil工具类,发送Get/Post请求 1. maven引入httpclien ...

  5. 6、react中的交互

    1.ajax 再react中使用ajax和直接使用ajax的用法是完全一样的,只要找好路径即可,但是也有不一样的地方,再react中是通过改变状态state来达到让组件重新渲染的效果,并且放ajax的 ...

  6. Linux系统如何设置开机自动运行脚本?

    大家好,我是良许. 在工作中,我们经常有个需求,那就是在系统启动之后,自动启动某个脚本或服务.在 Windows 下,我们有很多方法可以设置开机启动,但在 Linux 系统下我们需要如何操作呢? Li ...

  7. Nice Jquery Validator 常用规则整理

    一些简单规则 numeric: [/^[0-9]*$/, '请填写数值'], money: [/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/, "请填写有效的金额" ...

  8. ELK扫盲及搭建

    1. ELK部署说明 1.1ELK介绍: 1.1.1 ELK是什么? ELK是三个开源软件的缩写,分别表示:ElasticSearch , Logstash, Kibana , 它们都是开源软件,EL ...

  9. SpringBoot与(Security)安全

    1.简介 应用程序的两个主要区域 认证(Authentication): 是建立一个它声明的主体的过程(一个"主体" 一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统 ...

  10. 附024.Kubernetes全系列大总结

    Kubernetes全系列总结如下,后期不定期更新.欢迎基于学习.交流目的的转载和分享,禁止任何商业盗用,同时希望能带上原文出处,尊重ITer的成果,也是尊重知识.若发现任何错误或纰漏,留言反馈或右侧 ...