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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...