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

例如,分叉的侧干按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实现 蓝桥杯VIP 算法提高 项链

    算法提高 项链 时间限制:1.0s 内存限制:512.0MB 问题描述 由 n(1≤n≤100) 个珠子组成的一个项链,珠子有红.蓝.白三种颜色,各种颜色的珠子的安排顺序由键盘输入的字符串任意给定.蓝 ...

  2. Arrays.binarySearch和Collections.binarySearch的详细用法

    概述 binarysearch为在指定数组中查找指定值得索引值,该值在范围内找得到则返回该值的索引值,找不到则返回该值的插入位置,如果该值大于指定范围最大值则返回-(maxlength+1),而: i ...

  3. java实现第三届蓝桥杯星期几

    星期几 1949年的国庆节(10月1日)是星期六. 今年(2012)的国庆节是星期一. 那么,从建国到现在,有几次国庆节正好是星期日呢? 只要答案,不限手段! 可以用windows日历,windows ...

  4. CMD指令和GIT指令

    CMD指令 dir 显示当前文件夹的所有的文件目录 mkdir 创建文件夹 cd> 创建文件 rd 删除文件夹 del 删除文件 cls 清屏 Linux指令 查看版本 node -v node ...

  5. K8S-PV和PVC的实践

    一.什么是PV和PVC? PV的全称是Persistent Volume,翻译过来为持久化存储卷,是对底层的共享存储的一种抽象,PV由管理员进行创建和配置,主要含存储能力.访问模式.存储类型.回收策略 ...

  6. 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'xxxx'中的标识列指定显式值

    执行以下sql INSERT INTO [Country] VALUES (, N'中国', N'China', N'CN'); 提示错误 仅当使用了列列表并且 IDENTITY_INSERT 为 O ...

  7. jenkins 添加用户管理权限

    一.前言 小组开会通知 想把jenkins 构建的权限给开发,这样的话效率会增加.运维也不必每次帮助开发去构建发布. 1.规划 jenkins 四个项目分别对应三个人负责.项目下的只负责 CI.UAT ...

  8. 对学长TD课程通(.apk)的评价

    界面简介: 界面分为三个部分,第一部分是对课程表的添加,第二部分是对空闲教室的查询,第三部分是实时时间的展示和对软件的评价,实用性很强,仅限于本校学生,界面观赏性较差,从界面上对人的吸引力不够, 实用 ...

  9. Nlog打印日志到Influxdb数据库

    1.安装和使用Influxdb 安装部分网上资料比较多,也讲的比较详细,请自行百度. 下面大概讲下InfluxDB的写入和读取数据的方法. 我使用了InfluxData.Net包. 工具->Nu ...

  10. FTP 常用命令

    1. 准备 1.1 ftp 信息: ftp 服务器地址:192.168.168.10 用户名:will 密码:123 1.2 ftp 工具 使用 Windows 命令行: “开始” 按钮-> 搜 ...