觀察自然界中樹的分叉,一根主幹生長出兩個側乾,每個側乾又長出兩個側乾,以此類推,便生長出疏密有致的結構。這樣的生長結構,使用遞歸演算法可以模擬出來。 例如,分叉的側乾按45°的偏轉角度進行生長的遞歸示意圖如圖1所示。 圖1 生成樹的遞歸示意圖 按照樹分叉生長側乾的遞歸思想,編寫如下的HTML代碼。 < ...
觀察自然界中樹的分叉,一根主幹生長出兩個側乾,每個側乾又長出兩個側乾,以此類推,便生長出疏密有致的結構。這樣的生長結構,使用遞歸演算法可以模擬出來。
例如,分叉的側乾按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 繪製出的不同樹梢開紅花的分叉樹形