1. 程式人生 > >JavaScript圖形例項:遞迴生成樹

JavaScript圖形例項:遞迴生成樹

      觀察自然界中樹的分叉,一根主幹生長出兩個側幹,每個側幹又長出兩個側幹,以此類推,便生長出疏密有致的結構。這樣的生長結構,使用遞迴演算法可以模擬出來。

      例如,分叉的側幹按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  繪製出的不同樹梢開紅花的分叉