JavaScript圖形實例:遞歸生成樹

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

觀察自然界中樹的分叉,一根主幹生長出兩個側乾,每個側乾又長出兩個側乾,以此類推,便生長出疏密有致的結構。這樣的生長結構,使用遞歸演算法可以模擬出來。 例如,分叉的側乾按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  繪製出的不同樹梢開紅花的分叉樹形


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

-Advertisement-
Play Games
更多相關文章
  • 前一陣領導安排了一個任務:定時將集團資料庫某表的數據同步至我們公司伺服器的資料庫,感覺比寫增刪改查SQL有趣,特意記錄下來,希望能幫到有類似需求的小伙伴,如有錯誤也希望各位不吝指教 環境描述: 集團資料庫:Oracle 11g 部門資料庫:Oracle 11g 使用的軟體:PLSQL Develop ...
  • 教程 美團外賣Flutter動態化實踐 插件 native-draggable Native Drag and Drop for Flutter on iOS and MacOS flutter-mvvm Flutter plugin to rapidly create a Page with MV ...
  • 前言 上半年我定的OKR目標是幫助團隊將App切入Flutter,實現統一技術棧,變革成多端融合開發模式。Flutter目前是跨平臺方案中最有潛力實現我們這個目標的,不管是Hybird還是React Native,我們的項目都有落地應用,跨平臺一直是終端團隊所追求的技術,能夠快速研發和部署也是我們不 ...
  • 想要實現側邊欄,需要配合使用DrawerLayout。因為會用到嵌套佈局,所以根佈局不能是 ConstraintLayout,DrawerLayout 佈局下再嵌套兩個佈局,一個放置內容如 LinearLayout,一個放置側劃菜單,這裡使用 NavigationView 為了出現側邊欄點擊圖標和菜... ...
  • 前言: 最近在整理自己的技術棧,收集了一些自己認為比較重要的知識點分享給大家。 Runloop 1. iOS中觸摸事件傳遞和響應原理 2. 為什麼只有主線程的runloop是開啟的 3. 為什麼只在主線程刷新UI 4. PerformSelector和runloop的關係 5.GCD 在Runloo ...
  • 一、數組遍歷和其他 1.合併數組 數組.concat(數組1,數組2,數組3,...) 可以用來合併多個數組 //合併多個數組concat var arr = ["zhangsan","lisi","wangwu"]; var arr1 = ["zhaoli","liqi"]; var arr2 = ...
  • 頁面強行註入jQuery這個腳手架,然後可以用jQuery幹些事情了。 ...
  • 課程開始,今天學習了html的基本標簽: div + span: div和span兩個是雙標簽,html中有雙標簽和單標簽,下文中有單標簽介紹 ,雙標簽成雙成對出現例如: <div> <span></span> </div> 有<div>必定要有</div>這就是雙標簽的特性。 div和span沒有 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...