JavaScript圖形實例:迭代函數系統生成圖形

     迭代函數系統(Iterated Function System,IFS)能夠用來建立分形圖案,它是分形理論的重要分支,也是分形圖形處理中最富生命力並且最具備廣闊應用前景的領域之一。這一工做最先能夠追溯到Hutchinson於1981年對自類似集的研究。美國科學家M.F.Barnsley於1985年發展了這一分形構型系統,並命名爲迭代函數系統(Iterated Function System,IFS),後來又由Stephen Demko等人將其公式化,並引入到圖像合成領域中。IFS將待生成的圖像看作是由許多與總體類似的(自類似)或通過必定變換與總體類似的(自仿射)小塊拼貼而成。javascript

      IFS算法的基本過程是:html

(1)設定一個起始點(x0,y0)及總的迭代步數。java

(2)以機率P選取仿射變換W,形式爲算法

         x1=a*x0 + b*y0 + ecanvas

         y1=c*x0 + d*y0 + f數組

(3)以W做用點(x0,y0),獲得新座標(x1,y1);瀏覽器

(4)在屏幕上座標(x1,y1)處描點;dom

(5)令x0=x1,y0=y1,爲下一次迭代作準備;函數

(6)返第(2)步,進行下一次迭代,直到迭代次數大於總步數爲止。spa

      例如,在一個二維平面中,有2種仿射變換函數,能夠將一個點映射到另外一個位置:

①   x(n+1)= 0.5*x(n)-0.5*y(n)

      y(n+1) = 0.5*x(n)+0.5* y(n)

②   x(n+1) = 0.5 * x(n)+0.5 * y(n)+0.5

      y(n+1) = -0.5 * x(n) + 0.5 * y(n) + 0.5

      給定一個初始點 x(0),y(0),通過上面的仿射變換函數的映射,即可以獲得平面中許多點,這些點構成的圖形即是分形圖案。這個系統就叫作迭代函數系統。

      可是,一共有2個仿射變換函數,每次迭代要使用哪個呢?所以,須要給每一個仿射變換函數規定一個機率,按照機率來進行選擇。

      不妨設2個仿射變換函數的機率均爲0.5(各一半),此時算法步驟爲:

      (1)生成一個0~1之間的隨機數r;

      (2)判斷隨機數落入哪個機率空間,若r<=0.5,則使用仿射變換函數①;不然使用仿射變換函數②;

      (3)根據仿射變換函數計算出新座標(x1,y1),並在該座標處畫一個點;

       (4)循環執行這一過程,直到達到規定次數。

       按上面的算法步驟,編寫以下的HTML代碼。

<!DOCTYPE html>

<head>

<title>IFS生成圖形(一)</title>

<script type="text/javascript">

  function draw(id)

  {

     var canvas=document.getElementById(id);

     if (canvas==null)

        return false;

     var ctx=canvas.getContext('2d');

     ctx.fillStyle="#EEEEFF";

     ctx.fillRect(0,0,600,600);

     ctx.fillStyle="red";

     var x0=0;

     var y0=0;

     for (i=0; i<100000; i++)

     {

         r=Math.random();

         if (r<=0.5)

         {

             x1=0.5*x0-0.5*y0;

             y1=0.5*x0+0.5*y0;

          }

         else

         {

             x1=0.5*x0+0.5*y0+0.5;

             y1=-0.5*x0+0.5*y0+0.5;

         }

         ctx.fillText('.',x1*200+200,y1*200+200);

         x0 = x1;

         y0 = y1;

     }

   }

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="600" height="600" style="border:3px double #996633;">

</canvas>

</body>

</html>

       在瀏覽器中打開包含這段HTML代碼的html文件,能夠看到在瀏覽器窗口中繪製出的C曲線,如圖1所示。

圖1  利用IFS方法生成的C曲線

若是將上面的映射函數改成:

①    x(n+1)= -0.82*x(n)+0.16*y(n)+137

      y(n+1) = -0.16*x(n)+0.81* y(n)+14

②     x(n+1) = 0.44 * x(n)+0.32 * y(n)-3

      y(n+1) = -0.07 * x(n) + 0.61 * y(n) + 70

對應的HTML文件以下:

<!DOCTYPE html>

<head>

<title>IFS生成圖形(一)</title>

<script type="text/javascript">

  function draw(id)

  {

     var canvas=document.getElementById(id);

     if (canvas==null)

        return false;

     var ctx=canvas.getContext('2d');

     ctx.fillStyle="#EEEEFF";

     ctx.fillRect(0,0,600,600);

     ctx.fillStyle="green";

     var x0=0;

     var y0=0;

     for (i=0; i<100000; i++)

     {

         r=Math.random();

         if (r<=0.5)

         {

             x1=-0.82*x0+0.16*y0+137;

             y1=-0.16*x0+0.81*y0+14;

          }

         else

         {

             x1=0.44*x0+0.32*y0-3;

             y1=-0.07*x0+0.61*y0+70;

         }

         ctx.fillText('.',x1*2+100,y1*2+100);

         x0 = x1;

         y0 = y1;

     }

   }

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="600" height="600" style="border:3px double #996633;">

</canvas>

</body>

</html>

      在瀏覽器中打開包含這段HTML代碼的html文件,能夠看到在瀏覽器窗口中繪製出如圖2所示的樹葉圖案。

 

圖2  利用IFS生成的樹葉

      由圖1和圖2的生成程序可知,IFS方法中仿射變換的形式是相同的,不一樣的形狀取決於仿射變換的係數(a,b,c,d,e,f),而且對於一個比較複雜的圖形,可能須要多個不一樣的仿射變換來實現,而且每個仿射變換函數被調用的機率P也不必定是等同的。所以,6個仿射變換系數(a,b,c,d,e,f)和一個機率p便構成了IFS算法最關鍵的部分——IFS碼。

1.SierPinski三角形

SierPinski三角形採用的仿射變換函數爲:

W1: x1=0.5*x0

      y1=0.5*y0

W2: x1=0.5*x0 + 0.5

      y1=0.5*y0

W3: x1=0.5*x0 +0.25

      y1= 0.5*y0 +0.5

      可讓3個仿射變換函數的調用機率相同或相近,即機率p分別取0.333,0.333,0.334,保證p1+p2+p3=1。

      爲程序設計簡潔,將IFS碼中的6個係數和機率p採用數組保存。編寫以下的HTML代碼(爲了後面敘述方便,將這段程序代碼記爲「IFS生成圖形(二)」)。

<!DOCTYPE html>

<head>

<title>IFS生成圖形(二)</title>

<script type="text/javascript">

  function draw(id)

  {

     var canvas=document.getElementById(id);

     if (canvas==null)

        return false;

     var ctx=canvas.getContext('2d');

     ctx.fillStyle="#EEEEFF";

     ctx.fillRect(0,0,500,500);

     ctx.fillStyle="red";

     var a=[0.5,0.5,0.5];

     var b=[0,0,0];

     var c=[0,0,0];

     var d=[0.5,0.5,0.5];

     var e=[0,0.5,0.25];

     var f=[0,0,0.5];

     var p=[0.333,0.333,0.334];

     var x0=0;

     var y0=0;

     for (i=0; i<10000; i++)

     {

         r=Math.random();

         if (r<=p[0])

             index=0;

         else if (r<=p[0]+p[1])

             index=1;

         else

             index=2;

         x1=a[index]*x0+b[index]*y0+e[index];

         y1=c[index]*x0+d[index]*y0+f[index];

         ctx.fillText('.',x1*300+100,400-y1*300);

         x0 = x1;

         y0 = y1;

     }

   }

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="500" height="500" style="border:3px double #996633;">

</canvas>

</body>

</html>

      在瀏覽器中打開包含這段HTML代碼的html文件,能夠看到在瀏覽器窗口中繪製出的SierPinski三角形,如圖3所示。

 

圖3  SierPinski三角形

      前面介紹過,IFS的關鍵部分是IFS碼,不一樣的IFS碼生成不一樣的圖形。

      例如,「IFS生成圖形(二)」程序中的IFS碼定義改寫爲:

     var a=[0.5,0.5,0.5];

     var b=[0,0,0];

     var c=[0,0,0];

     var d=[0.5,0.5,0.5];

     var e=[0,0.5,0.5];

     var f=[0,0.5,0];

     var p=[0.333,0.333,0.334];

      則在瀏覽器窗口中繪製出如圖4所示的直角SierPinski三角形。

圖4  直角SierPinski三角形

2.蕨類植物

      可使用4個仿射變換函數來生成蕨類植物的圖案,編寫以下的HTML代碼(爲了後面敘述方便,將這段程序代碼記爲「IFS生成圖形(三)」)。

<!DOCTYPE html>

<head>

<title>IFS生成圖形(三)</title>

<script type="text/javascript">

  function draw(id)

  {

     var canvas=document.getElementById(id);

     if (canvas==null)

        return false;

     var ctx=canvas.getContext('2d');

     ctx.fillStyle="#EEEEFF";

     ctx.fillRect(0,0,600,600);

     ctx.fillStyle="green";

     var a=[0,0.2,-0.15,0.85];

     var b=[0,-0.26,0.28,0.04];

     var c=[0,0.23,0.26,-0.04];

     var d=[0.16,0.22,0.24,0.85];

     var e=[0,0,0,0];

     var f=[0,1.6,0.44,1.6];

     var p=[0.01,0.07,0.07,0.85];

     var x0=0;

     var y0=0;

     for (i=0; i<100000; i++)

     {

         r=Math.random();

         if (r<=p[0])

             index=0;

         else if (r<=p[0]+p[1])

             index=1;

         else if (r<p[0]+p[1]+p[2])

             index=2;

         else

             index=3;

         x1=a[index]*x0+b[index]*y0+e[index];

         y1=c[index]*x0+d[index]*y0+f[index];

         ctx.fillText('.',x1*50+300,550-y1*50);

         x0 = x1;

         y0 = y1;

     }

   }

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="600" height="600" style="border:3px double #996633;">

</canvas>

</body>

</html>

      在瀏覽器中打開包含這段HTML代碼的html文件,能夠看到在瀏覽器窗口中繪製出的蕨類植物圖案,如圖5所示。

圖5  IFS方法生成的蕨類植物(一)

     將「IFS生成圖形(三)」程序中的IFS碼定義改寫爲:

     var a=[0,0.21,-0.2,0.85];

     var b=[0,-0.25,0.26,0.1];

     var c=[0,0.25,0.23,-0.05];

     var d=[0.16,0.21,0.22,0.85];

     var e=[0,0,0,0];

     var f=[0,0.44,0,0.6];

     var p=[0.01,0.07,0.07,0.85];

      可在瀏覽器窗口中繪製出如圖6所示的蕨類植物。

圖6  IFS方法生成的蕨類植物(二)

3.樹形圖案

      將IFS生成圖形(二)程序中的IFS碼定義改寫爲:

     var a=[0.387,0.441,-0.468];

     var b=[0.430,-0.091,0.020];

     var c=[0.430,-0.009,-0.113];

     var d=[-0.387,-0.322,0.015];

     var e=[0.2560,0.4219,0.4];

     var f=[0.5220,0.5059,0.4];

     var p=[0.333,0.333,0.334];

      可在瀏覽器窗口中繪製出如圖7所示的嫩枝圖案。

 

圖7  嫩枝

 

 將「IFS生成圖形(三)」程序中的IFS碼定義改寫爲:

     var a=[0.01,-0.01,0.42,0.42];

     var b=[0,0,-0.42,0.42];

     var c=[0,0,0.42,-0.42];

     var d=[0.45,-0.45,0.42,0.42];

     var e=[0,0,0,0];

     var f=[0,0.4,0.4,0.4];

     var p=[0.05,0.15,0.4,0.4];

可在瀏覽器窗口中繪製出如圖8所示的樹形圖案。

圖8 樹形圖案(一)

 

      將「IFS生成圖形(三)」程序中的IFS碼定義改寫爲:

     var a=[0,0.42,0.42,0.1];

     var b=[0,-0.42,0.42,0];

     var c=[0,0.42,-0.42,0];

     var d=[0.5,0.42,0.42,0.4];

     var e=[0,0,0,0];

     var f=[0,0.4,0.4,0.4];

     var p=[0.05,0.4,0.4,0.15];

      可在瀏覽器窗口中繪製出如圖9所示的樹形圖案,並好像還有蟬在樹上。

 

圖9  樹上的蟬

    將「IFS生成圖形(三)」程序中的IFS碼定義改寫爲:

     var a=[0.03,-0.03,0.56,0.56];

     var b=[0,0,-0.56,0.56];

     var c=[0,0,0.56,-0.56];

     var d=[0.45,-0.45,0.56,0.56];

     var e=[0,0,0,0];

     var f=[0,0.4,0.4,0.4];

     var p=[0.05,0.15,0.4,0.4];

      可在瀏覽器窗口中繪製出如圖10所示的樹形圖案。

圖10  樹形圖案(二) 

    將「IFS生成圖形(三)」程序中的IFS碼定義改寫爲:

     var a=[-0.04,-0.65,0.41,0.52];

     var b=[0,0,0.46,-0.35];

     var c=[-0.19,0,-0.39,0.25];

     var d=[-0.47,0.36,0.61,0.74];

     var e=[-0.12,0.06,0.46,-0.48];

     var f=[0.3,1.56,0.4,0.38];

     var p=[0.25,0.25,0.25,0.25];

      可在瀏覽器窗口中繪製出如圖11所示的樹形圖案。

圖11  樹形圖案(三) 

       還可使用5個仿射變換函數來生成樹形圖案,參照「IFS生成圖形(二)」和「IFS生成圖形(三)」,適當添加一個條件選擇語句便可,這裏再也不給出源程序。

      5個仿射變換函數的IFS碼定義以下:

     var a=[0.195,0.462,-0.058,-0.035,-0.637];

     var b=[-0.488,0.414,-0.07,0.07,0];

     var c=[0.344,-0.252,0.453,-0.469,0];

     var d=[0.433,0.361,-0.111,-0.022,0.501];

     var e=[0.4431,0.2511,0.5976,0.4884,0.8562];

     var f=[0.2452,0.5692,0.0969,0.5069,0.2513];

     var p=[0.25,0.25,0.25,0.2,0.05];

      可在瀏覽器窗口中繪製出如圖12所示的樹形圖案。

圖12  樹形圖案(四)

4.雪花

    將「IFS生成圖形(三)」程序中的IFS碼定義改寫爲:

     var a=[0.255,0.255,0.255,0.37];

     var b=[0,0,0,-0.642];

     var c=[0,0,0,0.642];

     var d=[0.255,0.255,0.255,0.37];

     var e=[0.3726,0.1146,0.6306,0.6356];

     var f=[0.6714,0.2232,0.2232,-0.0061];

     var p=[0.2,0.2,0.2,0.4];

       可在瀏覽器窗口中繪製出如圖13所示的雪花圖案。

圖13  雪花圖案(一)

       還可使用5個仿射變換函數來生成雪花圖案,IFS碼定義以下:

     var a=[0.382,0.382,0.382,0.382,0.382];

     var b=[0,0,0,0,0];

     var c=[0,0,0,0,0];

     var d=[0.382,0.382,0.382,0.382,0.382];

     var e=[0.3072,0.6033,0.0139,0.1253,0.492];

     var f=[0.619,0.4044,0.4044,0.0595,0.0595];

     var p=[0.2,0.2,0.2,0.2,0.2];

       可在瀏覽器窗口中繪製出如圖14所示的雪花圖案。

 

圖14  雪花圖案(二) 

相關文章
相關標籤/搜索