天天看點

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

本節書摘來自異步社群《python極客項目程式設計 》一書中的第2章,第2.1節,作者 [美] mahesh venkitachalam,王海鵬 譯,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

我們可以用萬花尺玩具(如圖2-1所示)來繪制數學曲線。這種玩具由兩個不同尺寸的塑膠齒輪組成,一大一小。小的齒輪有幾個孔。把鋼筆或鉛筆放入一個孔,然後在較大齒輪(内部有齒)内旋轉裡面的小齒輪,保持筆與外輪接觸,可以畫出無數複雜而奇妙的對稱圖案。

在這個項目中,我們将用python來建立動畫,像萬花尺一樣繪制曲線。我們的spiro.py程式将用python和參數方程來描述程式的萬花尺齒輪的運動,并繪制曲線(我稱之為螺線)。我們可以将完成的畫圖儲存為png圖像檔案,并用指令行選項來指定參數或生成随機螺線。

在這個項目中,我們将學習如何在計算機上繪制螺線。還将學習以下幾點:

用turtle子產品建立圖形;

使用參數方程;

利用數學方程來生成曲線;

用線段來畫曲線;

用定時器來生成圖形動畫;

将圖形儲存為圖像檔案。

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

關于這個項目要注意:我在這個項目中選擇了turtle子產品用于說明展示,因為它很有趣,但turtle比較慢,如果性能很關鍵,就不适合用它來建立圖形(你對海龜有何期望?)。如果想快速畫圖,有更好的方法,後面的項目将探索一些可選方案。

在本節中,你将看到用參數方程來畫圓的簡單例子。參數方程将曲線上點的坐标表示為一個變量的函數,該變量稱為參數。參數方程讓繪制曲線變得容易,因為隻要将參數代入方程就能産生曲線。

注意

如果你現在不想學習這部分數學知識,可以跳到下一部分,讨論針對萬花尺項目的方程。

我們開始考慮用半徑r來描述一個圓的方程,圓心位于二維平面的原點。x、y坐标滿足該方程的所有點構成了圓。

現在,請考慮下面的方程:

這些方程是圓的參數表示,其中角θ是參數。這些方程中(x,y)的任何值,都滿足前面描述的圓的方程,x2 + y2= r2。如果讓θ從0變到2π,可以用這些方程來計算圓上對應的x和y坐标。圖2-2展示了這種方案。

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

記住,這兩個方程适用于圓心在坐标系原點的圓。将圓心轉換到點(a, b),就可以将圓置于xy平面的任何位置。是以更一般的參數方程就變成x = a + r cos(θ)和y = b + r cos(θ)。現在,讓我們來看看描述螺線的方程。

圖2-3展示了類似萬花尺運動的數學模型。該模型沒有齒輪,因為玩具中的齒輪隻是為了防止打滑,而在這裡不必擔心打滑。

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

在圖2-3中,c是較小的圓的圓心,p是筆尖。較大的圓半徑為r,較小的圓半徑為r。半徑之比表示如下:

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

将線段pc與小圓半徑r之比作為變量l(l = pc / r),它決定了筆尖離小圓圓心有多遠。然後,組合這些變量來表示p的運動,得到如下的參數方程:

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

這些曲線稱為内旋輪線和外旋輪線。雖然方程可能看起來有點吓人,但推導是非常簡單的。如果你想探索其中的數學,請參見維基百科。

圖2-4展示了如何用這些方程,基于參數的變化,産生一條曲線。通過改變參數r、r和l,可以産生變化無窮的迷人曲線。

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

将曲線繪制為一系列點之間的線段。如果這些點足夠接近,圖看起來就像平滑的曲線。真正玩過萬花尺就知道,這取決于使用的參數,萬花尺可能需要許多轉數來完成。要确定何時停止繪圖,就要利用萬花尺的周期性(即萬花尺圖案多久開始重複),研究内外圓的半徑之比:

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

分子分母除以它們的最大公約數(gcd),化簡該分數,分子就告訴我們需要多少圈才能完成曲線。例如,在圖2-4中,(r, r)的gcd是5。

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

下面是該分數化簡後的形式:

《Python極客項目程式設計 》——第2章 萬花尺 2.1 參數方程

這告訴我們,13圈後,曲線将開始重複。44告訴我們小圓圍繞其中心旋轉的圈數,它提示了曲線的形狀。在圖2-4中數一下,會看到圖形中花瓣或葉的數目恰好是44!

一旦用簡化形式表示了半徑比r/r,畫出螺線的參數θ範圍就是[0,2πr]。這告訴我們何時停止繪制特定的螺線。不知道該角度的結束範圍,就會循環不止,不必要地重複該曲線。

我們可以用python的turtle子產品來建立圖案。這是一個簡單的繪圖程式,模型是一隻海龜拖着尾巴穿過沙灘,留下圖案。turtle子產品包括了一些方法,用于設定筆(海龜的尾巴)的位置和顔色,以及其他有用的繪圖函數。如你所見,隻要少量繪圖函數,就可以建立漂亮的螺線。

例如,這個程式用turtle畫圓。輸入以下代碼,儲存為drawcircle.py,在python中運作它:

在1行,從導入turtle子產品開始。接下來,定義drawcircleturtle()方法,它在2行調用up()。這告訴python提筆。換句話說,讓筆離開虛拟的紙,這樣移動海龜也不會畫圖。開始繪圖之前,先定位海龜。

在3行,将海龜的位置設定為橫軸上的第一個點:(x + r, y),其中(x,y)是該圓的圓心。現在準備好畫圖了,是以在4行調用down()。在5行,利用range(0, 365, 5)開始循環,以5為步長遞增變量i,從0到360,變量i是角度參數,将傳入圓的參數方程,但首先在6行将它從度轉為弧度(大多數計算機程式的角度計算需要弧度)。

在7行,利用前面讨論過的參數方程計算圓的坐标,并設定相應的海龜位置,這樣就從海龜上一個位置畫線到新計算的位置(從技術上講,産生的是n邊多邊形,但因為用了很小的角度,n将非常大,多邊形看起來像一個圓)。

在8行,調用drawcircleturtle()來畫圓,在9行,調用mainloop(),它保持tkinter視窗打開,讓你可以欣賞你畫的圓(tkinter是python預設的gui庫)。

現在,我們準備好畫一些螺線了!