岁岁年年丶 發表於 2020-7-1 20:43:00

JavaScript图形实例:递归生成树

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