朱 勤 朱巍峰
(蘇州工業職業技術學院,江蘇 蘇州 215104)
在自然界中存在著很多自相似的結構,按照一定的比例放大或者縮小它的幾何尺寸,整個結構不會發生變化。對這些幾何結構的研究成為分形幾何學。科赫曲線就是一種典型的分形幾何。
先對科赫曲線做一個簡單的介紹。給定一條水平線段(圖1左)。將它分成三等份,以中間的線段為底邊,向上畫一個等邊三角形。最后再把中間的線段移除,我們就得到了一個一階的科赫曲線(如圖1 右)。
如果在一階科赫曲線上的每一個線段再做一次上述的操作,我們可以獲得二階的科赫曲線(圖2 左)。以此類推,我們可以得到三階的科赫曲線(圖2 右)。這樣的操作理論上可以進行無窮多次。結合圖1,可以看出,高階的科赫曲線的水平寬度始終是和圖1 左的直線相同,所以我們也可以認為圖1 左是一個零階的科赫曲線。

圖1 一階科赫曲線

圖2 二階和三階科赫曲線
這種曲線最早是海里格·馮·科赫提出的,所以被命名為科赫曲線。由于他的高階曲線和雪花的形狀很相似,所以也被成為雪花曲線。這種曲線的特點是具有自相似性。很容易可以看出這個曲線的局部和整體的結構是相同的。
在本論文中使用了Python3 語言進行編程。這種語言發展至今已經有了一個龐大的計算生態,除了本身的開源優勢以外,十四萬以上的第三方庫更是為它提供了無數的可能。
Python3的編程環境有很多,除了Python3 軟件自帶的集成開發環境(IDLE)以外,還有Anaconda 和PyCharm 等軟件。不同的軟件只要安裝了相同的庫都能實現相同的功能。筆者的編程環境使用的是Anaconda。
在python3 中要實現繪圖功能,需要導入相對應的庫。可以選擇的功能庫有很多,比如turtle 庫、tkinter 庫、matplotlib 庫、seaborn 庫等。本論文中的科赫曲線只是一個簡單的二維圖像,使用turtle 庫就能夠勝任了。
Turtle 是海龜的意思,所以也被稱為“海龜庫”,我們可以想象有一只小海龜,在畫板上爬行,它的爬行軌跡就是畫板上繪制的圖像。這只海龜就是我們的畫筆,只要通過一系列的指令去命令這只小海龜運動,就可以得到我們想要的圖像。常用的“海龜庫”指令可以控制運行方向,移動距離,旋轉角度,畫筆顏色,畫筆寬度等參數。使用“海龜庫”來繪制科赫曲線是一件非常簡單而且有趣的事情。
看上去有點復雜的科赫曲線要用程序來繪制,會不會很復雜呢?下面給出了繪制科赫曲線的源代碼和部分注釋。

3.2.1 turtle 庫導入
程序中第一行“import turtle as t”的作用是將turtle 庫導入到程序中,這樣在程序里面才可以使用turtle 庫中的相關指令。為了方便寫代碼,將它的庫名重命名為t。在下面的程序中以“t.”開頭的指令,都是turtle 庫中封裝好的功能。編代碼時只根據需要調用相關函數,設定相關參數就可以了。
3.2.2 科赫曲線繪制函數
“def DrawKoch(lenght,n):”自定義了一個功能函數,用來繪制科赫曲線,調用它時需要設定兩個參數,其中length 設置的是繪制曲線的長度(參考圖1 左,直線的長度),它的單位是像素,數值大小決定了整個圖形的尺寸。另一個參數n 設置的是科赫曲線的階數,以圖1 和圖2 為例,圖1 左的n 值為0,圖1 右的n值為1。圖2 左的n 值為2,圖2 右的n 值為3。
這個函數是本程序的核心。短短的7行代碼,就能夠實現繪制科赫曲線。修改參數length 就可以改變曲線的大小,修改參數n 就可以改變繪制曲線的階數。我們先假設length 為300 像素。然后對函數進行分析。
函數中的第一層是一個if 和else的分支結構。判斷條件是參數n。當n 為0 時,執行“t.fd(lenght)”其中“t.fd”的功能是讓“海龜”向前移動,參數length 是移動的距離,之前我們已經假設為300 像素。很顯然,當n 為0 時繪制出來的是一個零階曲線,如圖1 左所示是一條300 像素長的直線。
當我們要畫一階科赫曲線時,將參數n 設為1。那么第一層if 和else 分支結構的條件不成立,進入else 分支。這個分支中是一個循環結構。用一個angle 變量去遍歷四個角度值。具體來說就是這個循環結構要執行四次,第1 次,angle 為0,第2 次angle 為60,第3 次angle 為-120,第4 次angle 為60。循環結構的循環體中有兩條指令,其中“t.left(angle)”是讓“海龜”向左手方向轉過一定角度,角度值由參數angle 決定。所以每次循環“海龜”會先向左轉一個角度,然后再執行“DrawKoch(lenght/3,n-1)”指令。這里是這個函數中最重要的地方,它調用了繪制科赫曲線本身。但是長度變為原來的1/3,由于一開始length 設置為300,所以在這里就變成了100 像素,而且階數降1,變為0,相當于調用了函數“DrawKoch(100,0)”。分析一下可以看到n 為0,所以第一層if 和else的分支結構中判斷條件成立,執行“t.fd(100)”。所以此時調用“DrawKoch(lenght/3,n-1)”的結果相當于執行“t.fd(100)”。
最后我們再回到整個循環結構,可以看出,第1 次循環,“海龜”左轉0 度,然后前進100 像素。第2 次循環,“海龜”左轉60度,然后前進100 像素。第3 次循環,“海龜”左轉-120 度(即右轉120 度),然后前進100 像素。第4 次循環,“海龜”左轉60 度,然后前進100 像素。這里需要說明一點,“海龜”的初始方向是水平向右的。所以四次循環的整個移動軌跡就是圖1 右的一階科赫曲線。
如果要繪制二階、三階或者更高階的科赫曲線。只要改變main 函數的參數n 就可以了。這個n 就是科赫曲線的階數。由于在這個函數中用到了遞歸算法,即函數調用了自身,而每一次調用階數都會減1,當階數n 變為0 以后結束遞歸。比如在本程序中將主函數參數設置為main(300,3),那么繪制出來的就是3 階科赫曲線,和圖2 右一致。如果要繪制圖2 左這樣的二階科赫曲線,可以把主函數寫成main(300,2)。
3.2.3 主函數main
主函數main 是整個程序的起點,在這里需要對主要的參數進行設置。
其中“def main (lenght,n)”定義了一個主函數main。和“DrawKoch(lenght,n)”函數一樣,它也要設置長度和階數兩個參數。這個函數的主要功能是對“海龜”進行一些設置。
先用“t.setup(600,600)”指令創建一個600*600 像素的畫板。然后用“t.speed(0)”指令將“海龜”的爬行速度設為最大值,如果希望能夠看到圖像的繪制過程就需要對“t.speed(0)”中的參數進行設置了。用“t.pensize(2)”指令將“海龜”的寬度設為2 像素,如果希望曲線的更加粗,可以將寬度設置更大的值,但是需要注意曲線長度和寬度之間的比例。通過這三條指令為畫圖做好準備工作。
“t.pu()”是“t.penup()”的縮寫形式,代表將畫筆抬起,可以想象成“海龜”飛了起來,此時的“海龜”的移動不會再畫板上留下痕跡。然后使用“t.goto(-150,0)”指令讓“海龜”移動到畫板中X 坐標為-150 像素處。需要說明的是畫板的中心點是坐標原點,X軸正方向水平向右,Y 軸正方向是垂直向上。所以說“t.goto(-150,0)”應該在畫板中心的左側150 像素處。這個起點的位置需要根據科赫曲線的尺寸以及每次遍歷時移動的距離來合理的調整,由于本程序中將length 長度設置為300,所以將起點設置為-150 是比較合理的。如果將length 設置為400,那么顯然將起點設置為“t.goto(-200,0)”更為合適。最后再用“t.pd()”也就是“t.pendown()”,它的作用是落筆,讓“海龜”回到畫板上,然后再移動“海龜”就能留下爬行的軌跡了。這樣我們就做好了畫圖的準備。
接下來調用了繪制科赫曲線的函數“DrawKoch(lenght,n)”,進行圖形的繪制。繪制完畢以后使用“t.hideturtle()”將“海龜”隱藏。最后使用“t.done()”指令保持畫板,如果不加入“t.done()”指令,在隱藏了“海龜”以后,畫板會自動關閉,繪制好的圖畫一閃即逝,不利于觀察繪制結果。
3.2.4 函數調用
在整個程序中用到了兩次def 開頭的指令。分別定義了繪制科赫曲線的函數以及主函數。需要說明的是函數在定義以后如果沒有被調用是不起作用的。所以在程序的最后調用主函數main,同時設定長度為300 像素,階數為3。運行程序以后就能夠得到一個三階的科赫曲線。
本文設計了一個科赫曲線的繪制程序。這個程序可以在python3的環境中直接使用,只要簡單的修改最后一行主函數的參數值,理論上可以實現任意大小,任意階數的科赫曲線繪制。
在程序中稍加改動可以實現更多的效果。比如使用“t.screensize()”指令就可以對畫板參數進行設置,比如做如下設置t.screensize(800,600,“black”),其中的“800,600”參數就是畫板的尺寸,“black”是將畫板背景色設為黑色。也可以使用“t.pencolor()”指令來設置畫筆的顏色。例如使用“t.pencolor(”white“)“將畫筆顏色設為白色。在本文中的程序中這兩個參數都沒有設置,則會使用默認值,畫板默認為白色,畫筆默認為黑色。因此畫出來的是白底黑線的圖案。
如果我們在main 函數中“DrawKoch(lenght,n)“指令下方添加“t.right(120)“,這個指令是向右旋轉指令,參數120 是角度值120度。這樣在畫完一個科赫曲線以后,會向右旋轉120 度。然后再次調用“DrawKoch(lenght,n)”,畫第二個科赫曲線。畫完后再向右轉120,然后畫第三個科赫曲線。這樣就得到黑色夜空下的一片白色雪花。如果在繪圖過程中改變畫筆的顏色,就可以得到一片彩色的雪花了。
本文中使用的主要編程思路是使用遞歸的算法,讓函數自己調用自己,從而用簡短的程序實現了復雜的繪圖過程。只要通過修改函數中的參數就可以實現不同尺寸,不同階數的曲線繪制。常見的分形幾何圖除了科赫曲線以外,還有謝爾賓斯基三角形、謝爾賓斯基地毯、列維曲線、龍形曲線、分形樹、海岸線等。這些分形圖的繪制也可以用本文提供的程序結構來實現,只要把繪制程序中的算法部分替換掉就可以了。