跳轉到

📚專題:海龜與樹


📕 引言


當使用海龜畫完美麗的禪繞圖形之後,還可以畫什麼有重覆規律的圖案呢? 試著從生活中找尋靈感。
生活中的樹
在校園中,在公園裡,甚至在人行道上,常常可以看到不同種類的樹。樹可以美化景觀,也可以淨化空氣,對我們的環境有著許多的好處。
你知道樹是如何生長的嗎?來看看蘋果樹生長的縮時攝影:
(76秒, 資料來源:1)
利用資訊科技設備,可以產生電腦圖形(Computer Graphics),它的意思是利用電腦創造出的圖形,廣泛應用在建築、氣象、醫療、生物、娛樂等不同的領域。在此專題中,請利用海龜程式畫出樹的電腦圖形
建議先備課程

在學習本專題前,建議先完成 「海龜畫禪繞」 ,在學習概念銜接上會較為平順。





📙 問題


要使用程式來畫出樹,我們可能會有以下的問題:
  • 樹的構造有哪些?它的作用是什麼?
  • 樹的形狀像什麼?哪些因素會影響到樹的形狀?
  • 樹在藝術作品中的呈現方式?樹本身具備有哪些顏色?
  • 如何使用電腦程式畫出一棵樹?

想一想,還有想到與產生樹的圖形實作相關的問題嗎?





📗 搜尋


利用搜尋引擎,可以找到許多相關與樹相關的資料。
國小自然 植物的生長四要素
《看見台灣大樹》‖ 城市中的行道樹 榕樹、欒樹、木棉、樟樹、茄苳...你認識幾種?
一棵開花的樹 ◎席慕蓉
探索樹之美學!巴黎卡地亞當代藝術基金會《樹》從剪紙、攝影、插畫為大自然發聲
劉東啟教授:樹想告訴我們什麼?:2.演講
數以載情 — 古文詩詞意境的一些數學描繪
藝術的數學密碼 Ch 10. 數學美術館 (三):碎形 - 製造碎形的數學密碼 / 徐惠莉
談碎形與藝術:自我相似之結構套嵌
吳文成老師演講段落:碎形幾何的動態演變,從 H 碎形到樹碎形
蝴蝶效應|科學史上的今天:12/29


在找尋資料的過程,發現數學中的碎形可以用來描述自然界中雲、山脈、閃電、海岸線、雪片、植物根等等。到底什麼是碎形呢?

(6分06秒,可選中文字幕, 資料來源:2)


什麼是碎形

(資料來源:2)


碎形具有自我相似性,形狀中處處有相似的結構。

自我相似性

(資料來源:3)


瑞典數學家科赫提出的科赫曲線也是一種碎形,它不斷地在線段的中間三分之一處(如下圖綠色線段),形成新的正三角形的隆起。

koch_curve

(資料來源:2)


科赫曲線一直不斷地重複之後,看起來像什麼呢?

科赫曲線動畫

(資料來源:4)


樹也是由樹枝不斷地進行分支,有類似自我相似的形狀。

科赫曲線動畫

(資料來源:5)

碎形的概念可以幫助我們來理解樹的形狀。





📒 構思


要如何實作出樹的形狀呢?先來認識一下「遞迴」方法。
(1分51秒, 資料來源:6)

下面兩個圖形,也都是遞迴的視覺化例子,在自己的圖形中包含自己。

德羅斯特效應

(資料來源:7)


如何使用Python程式來表達遞迴呢?我們可以使用函式,並在函式的中間呼叫自己,不斷地重複。

無限遞迴

要小心,如果是無限遞迴的話,到最後會耗盡電腦的記憶體或產生系統錯誤。


如何避免無限遞迴呢?我們可以在每次的遞迴函式呼叫中傳遞「層」的參數,並設立遞迴的終止條件。

單線遞迴


當我們在遞迴函式中,呼叫自己兩次,就會有分支的情形。不斷的遞迴,就會不斷分支,直到終止條件發生,再逐一返回。

我們將使用這樣的構想,不斷地分支遞迴,來產生樹枝形狀的結構。

分支遞迴






📘 實作(4)

程式結構


我們使用以下的安排,做為程式的結構:

Python程式結構

  • 模組區 - 匯入內建或第三方函式庫
  • 全域變數 - 整個檔案內可共用的變數
  • 函式區 - 自訂的各種公用函式
  • 主程式 - 程式開始運作


使用程式註解,可以達到分區標示的效果,試著動手寫寫看。

範例程式 程式結構 - - - - - - - (專題實作1/4 新檔)

【長度2:07 章節時間如下】

  • 0:00 檔案儲存
  • 0:32 程式結構
# 模組區 ----------
from 海龜模組 import *

# 全域變數 ----------

# 函式區 ----------

# 主程式 ----------


完成()





單線遞迴


先以簡易的單線遞迴,來畫出一條直線。從下圖中,你看得出「向上畫線」與「後退」的執行順序嗎?
單線遞迴呼叫



如果像樹枝一樣漸漸彎曲,要如何做呢?先來找出遞迴樣式的規則:

彎曲遞迴樣式

看看「3.呼叫自己」之後的動作,像不像是「倒轉」動作呢?

(1分20秒, 資料來源:8)



原來要做出如樹支彎曲般的效果,就要在遞迴函式中適當之處加上「右轉」及「左轉」。

彎曲遞迴呼叫



試著動手實作看看。

範例程式 單線遞迴 - - - - - - - (專題實作2/4 接續)

【長度6:00 章節時間如下】

  • 2:11 單線遞迴
# 模組區 ----------------
from 海龜模組 import *

# 全域變數 ----------------

# 函式區 ----------------
def 初始設定() :
    左轉(90)

def 遞迴() :
    if  > 5 :
        畫點(10, 'red')
        return

    向前(50)
    畫點(10, 'black')
    右轉(20)

    遞迴( + 1)

    左轉(20)
    向後(50)

# 主程式 ----------------
初始設定()
遞迴(1)
完成()





碎形樹


要如何畫出如下的樹狀圖形呢?
遞迴樹


整理一下之前的兩種遞迴樣式與傳遞參數。

遞迴樣式



那樹狀圖形的遞迴樣式與傳遞參數又是什麼呢?

碎形樹樣式



下圖是2層分支遞迴的函式呼叫,看得出下圖中的執行順序嗎?(從黃色區塊開始)


碎形樹函式呼叫



範例程式 碎形樹 - - - - - - - (專題實作3/4 接續)

【長度8:03 章節時間如下】

  • 8:13 碎形樹
# 模組區 ----------------
from 海龜模組 import *

# 全域變數 ----------------
最大層數 = 5
轉角 = 20
開始長度 = 100
長縮減率 = 0.7

# 函式區 ----------------
def 初始設定() :
    左轉(90)
    速度('fastest')   

def 遞迴(, ) :
    if  > 最大層數 :
        畫點(10, 'red')
        return

    向前()
    畫點(10, 'black')

    右轉(轉角)
    遞迴( + 1,  * 長縮減率)

    左轉(轉角 * 2)
    遞迴( + 1,  * 長縮減率)

    右轉(轉角)
    向後()

# 主程式 ----------------
初始設定()
遞迴(1, 開始長度)
完成()        





碎形動畫


看看下面有關碎形樹的演示動畫(點選在youtube上觀看)。

(資料來源:9)


真是令人賞心悅目。可以使用海龜程式做出類似的效果嗎?

在畫碎形樹時,即使已將速度調整為fastest(最快),仍要花上一段時間才可以畫完,有辦法提升海龜的繪圖速度嗎?


tracer_manual

(資料來源: Python官網 海龜說明文件 )

上圖是海龜的說明文件,當我們把tracer關閉時,海龜會忽略繪圖動作,可以加快運算速度,等到算完時,再手動執行update更新繪圖畫面。

利用這樣的機制,可以試著做出簡單的碎形動畫。請動手試做看看。


範例程式 碎形動畫 - - - - - - - (專題實作4/4 接續)

【長度3:22 章節時間如下】

  • 16:18 碎形動畫
# 模組區 ----------------
from 海龜模組 import *

# 全域變數 ----------------
最大層數 = 5
轉角 = 20
開始長度 = 100
長縮減率 = 0.7

# 函式區 ----------------
def 初始設定() :
    左轉(90)
    速度('fastest')
    tracer(0, 0)

def 遞迴(, ) :
    if  > 最大層數 :
        畫點(10, 'red')
        return

    向前()
    畫點(10, 'black')

    右轉(轉角)
    遞迴( + 1,  * 長縮減率)

    左轉(轉角 * 2)
    遞迴( + 1,  * 長縮減率)

    右轉(轉角)
    向後()

# 主程式 ----------------
初始設定()

for  in range(90+1) :
    筆跡清除()
    轉角 =  
    遞迴(1, 開始長度)
    update()    

完成()        





📙 擴展(3)

樹與剪影


剪影(silhouette)是一種將人事物用單色描繪(通常為黑色),凸顯輪廓的藝術圖像。剪影也可應用在攝影上,利用逆光方式的攝影技巧,將人事物拍攝出有如剪影效果。
剪影
(資料來源:10)


為了凸顯剪影的效果,接下來會在夕陽剪影的背景下,使用海龜程式畫出碎形樹。

bgpic_manual

(資料來源: Python官網 海龜說明文件 )

上圖是海龜的說明文件,使用bgpic函式可以設定海龜的背景圖片(需使用gif圖檔)。


為了讓碎形樹更像樹,在傳遞的參數上,使用到「長」、「寬」,隨著遞迴的層次,會逐步縮減。

傳遞參數

試著動手實作看看。


記得要下載範例夕陽圖片
本範例程式需一張夕陽圖片,請挑選一張下載(右鍵「另存圖片」),下載的圖片需與Python程式在同一資料夾。圖片的檔名要與程式中的檔名相同。
sunset1 sunset2 sunset3
圖片來源 https://www.pexels.com
範例程式 樹與剪影 - - - - - - - (專題實作1/3 接續)

【長度7:43 章節時間如下】

  • 19:42 樹與剪影
# 需匯入sunset1.gif(海龜便利貼:背景->匯入)

# 模組區 ----------------
from 海龜模組 import *

# 全域變數 ----------------
最大層數 = 11
轉角 = 20
開始長度 = 300
長縮減率 = 0.7
開始寬度 = 40
寬縮減率 = 0.7

# 函式區 ----------------
def 初始設定() :
    左轉(90)
    速度('fastest')
    tracer(50, 0)
    視窗設定(1000, 1000)
    畫筆顏色('black')
    停筆()
    走到(0,-500)
    bgpic('sunset1.gif')

def 遞迴(, , ) :
    if  > 最大層數 :
        return

    下筆()
    畫筆尺寸()
    向前()
    停筆()

    右轉(轉角)
    遞迴( + 1,  * 長縮減率,  * 寬縮減率)

    左轉(轉角 * 2)
    遞迴( + 1,  * 長縮減率,  * 寬縮減率)

    右轉(轉角)
    向後()

# 主程式 ----------------

初始設定()

遞迴(1, 開始長度, 開始寬度)    

完成()        





樹與混沌


在上一個範例中,畫出來的樹似乎太過「規則」,與真正的樹不一樣。
先長看看實際的樹,在生長時會受到影響的因素。


(影片長度39秒,資料來源:11)


樹在生長時的空氣、光照、風雨等變化,如同蝴蝶效應一樣,細微的改變累積,最後會產生長期的連鎖反應,讓樹有了某些的不規則形變化,這是一種自然界常有的混沌狀態。

我們使用範圍內的隨機長度、寬度與轉角角度,簡單模擬出這種混沌狀態。

長度混沌


角度混沌


動手實作看看。

記得要下載範例夕陽圖片
本範例程式需一張夕陽圖片,請挑選一張下載(右鍵「另存圖片」),下載的圖片需與Python程式在同一資料夾。圖片的檔名要與程式中的檔名相同。
sunset1 sunset2 sunset3
圖片來源 https://www.pexels.com
範例程式 樹與混沌 - - - - - - - (專題實作2/3 接續)

【長度8:07 章節時間如下】

  • 27:27 樹與混沌
# 需匯入sunset1.gif(海龜便利貼:背景->匯入)

# 模組區 ---------------
from 海龜模組 import *
import random as 隨機

# 全域變數 ---------------
最大層數 = 11
開始長度 = 300
長縮減最小 = 0.6
長縮減最大 = 0.8
開始寬度 = 40
寬縮減率 = 0.7
轉角最小 = 10
轉角最大 = 40
夾角最小 = 30
夾角最大 = 70

# 函式區 ---------------
def 初始設定() :
    左轉(90)
    速度('fastest')
    tracer(50, 0)
    視窗設定(1000, 1000)
    畫筆顏色('black')
    停筆()
    走到(0,-500)
    bgpic('sunset1.gif')


def 遞迴(, , ) :
    if  > 最大層數 :
        return

    下筆()
    畫筆尺寸()
    向前()
    停筆()

    轉角 = 隨機.randint(轉角最小,轉角最大)
    右轉(轉角)
    長縮減率 = 隨機.uniform(長縮減最小, 長縮減最大)
    遞迴( + 1,  * 長縮減率,  * 寬縮減率)

    夾角 = 隨機.randint(夾角最小,夾角最大)
    左轉(夾角)
    長縮減率 = 隨機.uniform(長縮減最小, 長縮減最大)
    遞迴( + 1,  * 長縮減率,  * 寬縮減率)

    右轉(夾角 - 轉角)
    向後()

# 主程式 ---------------
初始設定()

遞迴(1, 開始長度, 開始寬度)
update()

完成()        





樹與葉


有了混沌狀態的簡易模擬,看起來就更像樹了。不過畫起來的感覺有點蕭瑟,因為都是枯枝。
為了讓樹有點生氣,再加上葉子的設計。
葉子設計



動手實作看看。

記得要下載範例夕陽圖片
本範例程式需一張夕陽圖片,請挑選一張下載(右鍵「另存圖片」),下載的圖片需與Python程式在同一資料夾。圖片的檔名要與程式中的檔名相同。
sunset1 sunset2 sunset3
圖片來源 https://www.pexels.com
範例程式 樹與葉 - - - - - - - (專題實作3/3 接續)

【長度5:52 章節時間如下】

  • 35:36 樹與葉
# 需匯入sunset1.gif(海龜便利貼:背景->匯入)

# 模組區 ---------------
from 海龜模組 import *
import random as 隨機

# 全域變數 ---------------
最大層數 = 11
開始長度 = 300
長縮減最小 = 0.6
長縮減最大 = 0.8
開始寬度 = 40
寬縮減率 = 0.7
轉角最小 = 10
轉角最大 = 40
夾角最小 = 30
夾角最大 = 70
葉直徑 = 6
葉層數 = 5

# 函式區 ---------------
def 初始設定() :
    左轉(90)
    速度('fastest')
    tracer(50, 0)
    視窗設定(1000, 1000)
    畫筆顏色('black')
    停筆()
    走到(0,-500)
    bgpic('sunset1.gif')
    隨機.seed(1)

def () :
    畫點(葉直徑, 'black')
    for  in range(4) :
        向前(葉直徑 * 2)
        畫點(葉直徑, 'black')
        向後(葉直徑 * 2)
        右轉(90)

def 遞迴(, , ) :
    if  > 最大層數 :
        return
    elif  > 最大層數 - 葉層數 :
        ()

    下筆()
    畫筆尺寸()
    向前()
    停筆()

    轉角 = 隨機.randint(轉角最小,轉角最大)
    右轉(轉角)
    長縮減率 = 隨機.uniform(長縮減最小, 長縮減最大)
    遞迴( + 1,  * 長縮減率,  * 寬縮減率)

    夾角 = 隨機.randint(夾角最小,夾角最大)
    左轉(夾角)
    長縮減率 = 隨機.uniform(長縮減最小, 長縮減最大)
    遞迴( + 1,  * 長縮減率,  * 寬縮減率)

    右轉(夾角 - 轉角)
    向後()

# 主程式 ---------------
初始設定()
遞迴(1, 開始長度, 開始寬度)
update()
完成()        





  1. 800 days in 8 minutes - Growing Plants Time Lapse Compilation, by Boxlapse , youtube連結 

  2. 藝術的數學密碼 Ch 10. 數學美術館 (三):碎形 - 碎形是什麼? / 徐惠莉, by 臺灣通識網General Education TW-開放式課程GET , youtube連結 

  3. 左圖 https://www.pexels.com/zh-tw/photo/5345030/ . 右圖來源 吳文成老師教學網站 碎形幾何內涵與 Logo 程式繪圖  

  4. 由 英文維基百科的Dino, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=3872598 

  5. Fractal Foundation, https://fractalfoundation.org/OFC/OFC-1-1.html 

  6. 不插電 程式運算邏輯入門5 遞迴(recursion), by Sophia Hsiao , youtube連結 

  7. 由 Designer: Jan MissetUploader: Alf van Beem - 自己的作品, 公有領域, https://commons.wikimedia.org/w/index.php?curid=30739029 

  8. THIS IS THE BEST REVERSE VIDEO I EVER MADE!, by Mr. Reverse, youtube連結 

  9. Fractal Tree Morph 4K UHD 60FPS, by syntaxerror147, youtube連結 

  10. 左圖來源 Public Domain, https://commons.wikimedia.org/w/index.php?curid=1449030 ; 右圖來源 By Bob Jagendorf from Manalapan, NJ, USA - Lady Liberty At Sunset, CC BY 2.0, https://commons.wikimedia.org/w/index.php?curid=4203048 

  11. 國小自然 植物的生長四要素, by 台北酷課雲, youtube連結