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

来源:https://www.cnblogs.com/cs-whut/archive/2020/07/04/13235992.html
-Advertisement-
Play Games

迭代函數系統(Iterated Function System,IFS)可以用來創建分形圖案,它是分形理論的重要分支,也是分形圖形處理中最富生命力而且最具有廣闊應用前景的領域之一。這一工作最早可以追溯到Hutchinson於1981年對自相似集的研究。美國科學家M.F.Barnsley於1985年發 ...


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

      IFS演算法的基本過程是:

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

(2)以概率P選取仿射變換W,形式為

         x1=a*x0 + b*y0 + e

         y1=c*x0 + d*y0 + f

(3)以W作用點(x0,y0),得到新坐標(x1,y1);

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

(5)令x0=x1,y0=y1,為下一次迭代做準備;

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

      例如,在一個二維平面中,有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  雪花圖案(二) 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ver: 1.0 博客:https://www.cnblogs.com/Rohn 本文介紹了Shell常用的結構化語句。 數組 數組(Array)是若幹數據的集合,其中的每一份數據都稱為元素(Element)。 Bash只支持一維數組(不支持多維數組),初始化時不需要定義數組大小,理論上可以存放無限 ...
  • hbase2.1.9 centos7 完全分散式 搭建隨記 這裡是當初在三個ECS節點上搭建hadoop+zookeeper+hbase+solr的主要步驟,文章內容未經過潤色,請參考的同學搭配其他博客一同使用,並記得根據實際情況調整相關參數 1. 指定位置解壓 2. vi /etc/profile ...
  • zookeeper3.5.5 centos7 完全分散式 搭建隨記 這裡是當初在三個ECS節點上搭建hadoop+zookeeper+hbase+solr的主要步驟,文章內容未經過潤色,請參考的同學搭配其他博客一同使用,並記得根據實際情況調整相關參數 0.prepare 準備奇數台已經配置好jdk的 ...
  • Hadoop2.7.7 centos7 完全分散式 配置與問題隨記 這裡是當初在三個ECS節點上搭建hadoop+zookeeper+hbase+solr的主要步驟,文章內容未經過潤色,請參考的同學搭配其他博客一同使用,並記得根據實際情況調整相關參數。 0.prepare jdk,推薦1.8 關閉防 ...
  • 我們需要接受失望,因為它是有限的;我們不會失去希望,因為它是無窮的。 一、概述 隨著時間和業務的發展,資料庫中表的數據量會越來越大,相應地,數據操作,增刪改查的開銷也會越來越大。因此,把其中一些大表進行拆分到多個資料庫中的多張表中。 本篇文章是基於非事務消息的非同步確保的方式來完成分庫分表中的事務問題 ...
  • MySQL索引 索引分類 最左首碼原則 覆蓋索引 索引下推 聯合索引順序 What's Index ? 索引就是幫助RDBMS高效獲取數據的數據結構。 索引可以讓我們避免一行一行進行全表掃描。它的價值就是可以幫助你對數據進行快速定位。 索引分類 按照功能邏輯來分 普通索引 INDEX(col_nam ...
  • Flutter第一個應用--踩坑之路 安裝 參照官網教程(這裡)下載解壓,以及設置環境變數即可。 如果你是中國用戶(當然了,我們都是),參考這篇文章Using Flutter in China,設置一下中國的鏡像。 比如我用的是zsh,那我的設置如下: export PUB_HOSTED_URL=h ...
  • JS數據類型判斷 JavaScript 中常見數據類型有Number、String、Boolean、Object、Array、Json、Function、Date、RegExp、Error、undefined、Null等十幾種。ES6還有新增的數據類型有Symbol、Set、Map等。在實際應用中, ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...