JavaScript图形实例:递归生成树
<p><span style="font-size: 14px"> 观察自然界中树的分叉,一根主干生长出两个侧干,每个侧干又长出两个侧干,以此类推,便生长出疏密有致的结构。这样的生长结构,使用递归算法可以模拟出来。</span></p><p> 例如,分叉的侧干按45°的偏转角度进行生长的递归示意图如图1所示。</p>
<p style="text-align: center"> <img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701203433701-93599747.jpg"></p>
<p align="center">图1 生成树的递归示意图</p>
<p style="margin-left: 30px">按照树分叉生长侧干的递归思想,编写如下的HTML代码。</p>
<p style="margin-left: 30px"><!DOCTYPE html></p>
<p style="margin-left: 30px"><head></p>
<p style="margin-left: 30px"><title>递归分形树(一)</title></p>
<p style="margin-left: 30px"></head></p>
<p style="margin-left: 30px"><body></p>
<p style="margin-left: 30px"><canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;"></p>
<p style="margin-left: 30px"></canvas></p>
<p style="margin-left: 30px"><script type="text/javascript"></p>
<p style="margin-left: 30px"> var canvas = document.getElementById('myCanvas');</p>
<p style="margin-left: 30px"> var ctx = canvas.getContext('2d');</p>
<p style="margin-left: 30px"> var maxdepth =4;</p>
<p style="margin-left: 30px"> var curdepth = 0;</p>
<p style="margin-left: 30px"> var alph=Math.PI/4;</p>
<p style="margin-left: 30px"> function growtree()</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> ctx.translate(300,380);</p>
<p style="margin-left: 30px"> branch(-Math.PI/2);</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> function branch(angle)</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> curdepth++;</p>
<p style="margin-left: 30px"> ctx.save();</p>
<p style="margin-left: 30px"> ctx.strokeStyle = "green";</p>
<p style="margin-left: 30px"> ctx.lineWidth = 6;</p>
<p style="margin-left: 30px"> ctx.rotate(angle);</p>
<p style="margin-left: 30px"> ctx.beginPath();</p>
<p style="margin-left: 30px"> ctx.moveTo(0,0);</p>
<p style="margin-left: 30px"> ctx.lineTo(100,0);</p>
<p style="margin-left: 30px"> ctx.stroke();</p>
<p style="margin-left: 30px"> ctx.translate(100,0);</p>
<p style="margin-left: 30px"> ctx.scale(0.75,0.75);</p>
<p style="margin-left: 30px"> if(curdepth <= maxdepth)</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> branch(alph);</p>
<p style="margin-left: 30px"> branch(-alph);</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> ctx.restore();</p>
<p style="margin-left: 30px"> curdepth--;</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> growtree();</p>
<p style="margin-left: 30px"></script></p>
<p style="margin-left: 30px"></body></p>
<p style="margin-left: 30px"></html></p>
<p> 在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出分叉树形,如图2所示。</p>
<p align="center"> <img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701203658346-392817420.png"></p>
<p align="center">图2 递归深度maxdepth =4,alph=45°的分叉树形</p>
<p> 若将递归深度“maxdepth=4”修改为“maxdepth=12”,则在浏览器窗口中绘制出如图3所示的分叉树形。</p>
<p style="text-align: center"> <img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701203720766-443742964.png"></p>
<p align="center">图3 递归深度maxdepth =12,alph=45°的分叉树形</p>
<p> 若将递归深度“maxdepth=4”修改为“maxdepth=10”,分叉偏转角度从45°(alph=Math.PI/4)修改为30°(alph=Math.PI/6),则在浏览器窗口中绘制出如,4所示的分叉树形。 </p>
<p style="text-align: center"><img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701203804338-52178640.png"> 图4 递归深度maxdepth =10,alph=30°的分叉树形</p>
<p> 由图3和图4可知,分叉的偏转角度不同,树形也会不同。实际上,自然界中树的侧干的生长不会按同一个角度进行分叉的,若将分叉的偏转角度取随机值,编写如下的HTML代码。</p>
<p style="margin-left: 30px"><!DOCTYPE html></p>
<p style="margin-left: 30px"><head></p>
<p style="margin-left: 30px"><title>递归分形树(二)</title></p>
<p style="margin-left: 30px"></head></p>
<p style="margin-left: 30px"><body></p>
<p style="margin-left: 30px"><canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;"></canvas></p>
<p style="margin-left: 30px"><script type="text/javascript"></p>
<p style="margin-left: 30px"> var canvas = document.getElementById('myCanvas');</p>
<p style="margin-left: 30px"> var ctx = canvas.getContext('2d');</p>
<p style="margin-left: 30px"> var maxdepth =10;</p>
<p style="margin-left: 30px"> var curdepth = 0;</p>
<p style="margin-left: 30px"> function growtree()</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> ctx.translate(300,380);</p>
<p style="margin-left: 30px"> branch(-Math.PI/2);</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> function branch(angle)</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> curdepth++;</p>
<p style="margin-left: 30px"> ctx.save();</p>
<p style="margin-left: 30px"> ctx.strokeStyle = "green";</p>
<p style="margin-left: 30px"> ctx.lineWidth = 6;</p>
<p style="margin-left: 30px"> ctx.rotate(angle);</p>
<p style="margin-left: 30px"> ctx.beginPath();</p>
<p style="margin-left: 30px"> ctx.moveTo(0,0);</p>
<p style="margin-left: 30px"> ctx.lineTo(100,0);</p>
<p style="margin-left: 30px"> ctx.stroke();</p>
<p style="margin-left: 30px"> ctx.translate(100,0);</p>
<p style="margin-left: 30px"> ctx.scale(0.75,0.75);</p>
<p style="margin-left: 30px"> if(curdepth <= maxdepth)</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> branch(randomRange(0,Math.PI/4));</p>
<p style="margin-left: 30px"> branch(randomRange(-Math.PI/4,0));</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> ctx.restore();</p>
<p style="margin-left: 30px"> curdepth--;</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> function randomRange(min,max)</p>
<p style="margin-left: 30px"> {</p>
<p style="margin-left: 30px"> return Math.random()*(max-min) + min;</p>
<p style="margin-left: 30px"> }</p>
<p style="margin-left: 30px"> growtree();</p>
<p style="margin-left: 30px"></script></p>
<p style="margin-left: 30px"></body></p>
<p style="margin-left: 30px"></html></p>
<p> 在浏览器中打开包含这段HTML代码的html文件,在浏览器窗口中可能会绘制出如图5所示的分叉树形。</p>
<p align="center"> <img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701203935663-601276602.png"></p>
<p align="center">图5 分叉树形</p>
<p> 不断地刷新浏览器窗口,可以随机绘制出不同的分叉树形,如图6所示。</p>
<p style="text-align: center"> <img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701204006968-1321036758.gif"></p>
<p align="center">图6 绘制出的不同分叉树形</p>
<p align="left"> 如果将递归树形的生成元改为如图7所示的三分叉,即在上面HTML文件中的两行代码</p>
<p> branch(randomRange(0,Math.PI/4));</p>
<p> branch(randomRange(-Math.PI/4,0));</p>
<p align="left">中间加上一行代码 branch(0); 再将递归深度“var maxdepth =10;”修改为“var maxdepth =6;”,则在浏览器窗口中可能会绘制出如图8所示的分叉树形。</p>
<p align="center"> <img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701204028620-919486233.png"></p>
<p align="center">图7 三分叉生成元</p>
<p align="center"><img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701204102390-960584528.png"></p>
<p> </p>
<p style="text-align: center"> 图8 三分叉递归树形</p>
<p style="margin-left: 30px" align="left">我们可以在树梢画一个红色小圆,表示树儿开花了,编写如下的HTML文件。</p>
<p style="margin-left: 30px" align="left"><!DOCTYPE html></p>
<p style="margin-left: 30px" align="left"><head></p>
<p style="margin-left: 30px" align="left"><title>递归分形树(三)</title></p>
<p style="margin-left: 30px" align="left"></head></p>
<p style="margin-left: 30px" align="left"><body></p>
<p style="margin-left: 30px" align="left"><canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;"></canvas></p>
<p style="margin-left: 30px" align="left"><script type="text/javascript"></p>
<p style="margin-left: 30px" align="left"> var canvas = document.getElementById('myCanvas');</p>
<p style="margin-left: 30px" align="left"> var ctx = canvas.getContext('2d');</p>
<p style="margin-left: 30px" align="left"> var maxdepth =10;</p>
<p style="margin-left: 30px" align="left"> var curdepth = 0;</p>
<p style="margin-left: 30px" align="left"> function growtree()</p>
<p style="margin-left: 30px" align="left"> {</p>
<p style="margin-left: 30px" align="left"> ctx.translate(300,380);</p>
<p style="margin-left: 30px" align="left"> branch(-Math.PI/2);</p>
<p style="margin-left: 30px" align="left"> }</p>
<p style="margin-left: 30px" align="left"> function branch(angle)</p>
<p style="margin-left: 30px" align="left"> {</p>
<p style="margin-left: 30px" align="left"> curdepth++;</p>
<p style="margin-left: 30px" align="left"> ctx.save();</p>
<p style="margin-left: 30px" align="left"> ctx.strokeStyle = "green";</p>
<p style="margin-left: 30px" align="left"> ctx.lineWidth = 6;</p>
<p style="margin-left: 30px" align="left"> ctx.rotate(angle);</p>
<p style="margin-left: 30px" align="left"> ctx.beginPath();</p>
<p style="margin-left: 30px" align="left"> ctx.moveTo(0,0);</p>
<p style="margin-left: 30px" align="left"> ctx.lineTo(100,0);</p>
<p style="margin-left: 30px" align="left"> ctx.stroke();</p>
<p style="margin-left: 30px" align="left"> ctx.translate(100,0);</p>
<p style="margin-left: 30px" align="left"> ctx.scale(0.75,0.75);</p>
<p style="margin-left: 30px" align="left"> if(curdepth < maxdepth)</p>
<p style="margin-left: 30px" align="left"> {</p>
<p style="margin-left: 30px" align="left"> branch(randomRange(0,Math.PI/4));</p>
<p style="margin-left: 30px" align="left"> branch(randomRange(-Math.PI/4,0));</p>
<p style="margin-left: 30px" align="left"> }</p>
<p style="margin-left: 30px" align="left"> if(curdepth == maxdepth)</p>
<p style="margin-left: 30px" align="left"> {</p>
<p style="margin-left: 30px" align="left"> ctx.fillStyle = '#ff0000';</p>
<p style="margin-left: 30px" align="left"> ctx.beginPath();</p>
<p style="margin-left: 30px" align="left"> ctx.arc(0,0,20,0,Math.PI*2,true);</p>
<p style="margin-left: 30px" align="left"> ctx.fill();</p>
<p style="margin-left: 30px" align="left"> }</p>
<p style="margin-left: 30px" align="left"> ctx.restore();</p>
<p style="margin-left: 30px" align="left"> curdepth--;</p>
<p style="margin-left: 30px" align="left"> }</p>
<p style="margin-left: 30px" align="left"> function randomRange(min,max)</p>
<p style="margin-left: 30px" align="left"> {</p>
<p style="margin-left: 30px" align="left"> return Math.random()*(max-min) + min;</p>
<p style="margin-left: 30px" align="left"> }</p>
<p style="margin-left: 30px" align="left"> growtree();</p>
<p style="margin-left: 30px" align="left"></script></p>
<p style="margin-left: 30px" align="left"></body></p>
<p style="margin-left: 30px" align="left"></html></p>
<p> 在浏览器中打开包含这段HTML代码的html文件,在浏览器窗口中可能会绘制出如图9所示的分叉树形。</p>
<p align="center"><img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701204142939-107907074.png"></p>
<p> </p>
<p style="text-align: center"> 图9 树梢开红花的分叉树形</p>
<p> 不断地刷新浏览器窗口,可以随机绘制出不同的分叉树形,如图10所示。</p>
<p align="center"><img src="https://img2020.cnblogs.com/blog/1485495/202007/1485495-20200701204203449-940735420.gif"> </p>
<p align="center">图10 绘制出的不同树梢开红花的分叉树形</p><br><br>
来源:https://www.cnblogs.com/cs-whut/p/13221406.html
頁:
[1]