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

例如,分叉的侧干按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实现 LeetCode 142 环形链表 II(二)

    142. 环形链表 II 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始 ...

  2. java算法集训代码填空题练习2

    1 连续数的公倍数 为什么1小时有60分钟,而不是100分钟呢?这是历史上的习惯导致. 但也并非纯粹的偶然:60是个优秀的数字,它的因子比较多. 事实上,它是1至6的每个数字的倍数.即1,2,3,4, ...

  3. 小师妹学JavaIO之:目录还是文件

    目录 简介 linux中的文件和目录 目录的基本操作 目录的进阶操作 目录的腰疼操作 总结 简介 目录和文件傻傻分不清楚,目录和文件的本质到底是什么?在java中怎么操纵目录,怎么遍历目录.本文F师兄 ...

  4. zabbix内存百分比监控告警

    本文结合配置内存不足10%触发报警的需求,zabbix给我们提供的模板,里面都已经配置好了item和trigger.但是给我们的模板是当内存小于20M的时候才会触发报警,这样不能满足我们的需求,我们需 ...

  5. 停电后,在UPS电源下服务器自动关机脚本

    一年总有那么几次莫明停电,公司的服务器经不起这样的折腾 写了一个断电后UPS备用电源自动关机的脚本 原理就是检测路由器网关是否能ping通,长时间持续ping不通视为停电了 路由器不要接到ups上 用 ...

  6. 网页元素居中的n种方法

    导语:元素居中对齐在很多场景看上去很和谐很漂亮.除此之外,对于前端开发面试者的基础也是很好的一个考察点.下面跟着作者的思路,一起来看下吧. 场景分析 一个元素,它有可能有背景,那我要它的背景居中对齐 ...

  7. Python format格式化函数

    参考资料:https://www.runoob.com/python/att-string-format.html 在学习Python的时候碰到了一个很有趣的格式化输入的技巧,下面记录在此. Pyth ...

  8. vim改变字体和查看映射的(mapping)命令

    临时修改.通过gvim Command MODE,输入如下命令即可: Linux/Unix: set guifont=Monospace\空格14 注意这里需要对空格使用\进行转义 Windows:  ...

  9. 重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不 ...

  10. ComplexHeatmap|根据excel表绘制突变景观图(oncoplot)

    本文首发于“生信补给站”:https://mp.weixin.qq.com/s/8kz2oKvUQrCR2_HWYXQT4g 如果有maf格式的文件,可以直接oncoplot包绘制瀑布图,有多种展示和 ...