天天看點

用 Mathematica 玩轉環面

環面及其變體

要玩轉環面,先要構造出環面,然後才可以談其它。本節将介紹如何從環面出發,用數學公式讓它發生各種形變,以及如何變化參數,生成動畫。

01

構造環面

我們都很熟悉圓的參數方程,比如對一個半徑為 R 的圓心位于原點的圓,圓上的點的坐标 (x, y) 滿足以下方程:

用 Mathematica 玩轉環面

這個方程雖然準确,卻不容易根據它直接畫出圖形。為了能構造性的生成曲線,采用所謂“參數方程”比較友善,也就是把 x、y 當作另一個參數 t 的函數。上述圓方程的一種可能的參數方程是:

用 Mathematica 玩轉環面

參數 t 可以看作圓上的點和圓心所連成的直線和 x 軸的夾角,t 從 0 取到 2π,就完成了繞圓一周,也就畫出了一個圓。有了圓的參數方程,就不難構造出環面的參數方程。直覺想象一下,把一個圓 B 放在 xy 平面上,再有一個垂直于 xy 平面的立起來的圓 A,A 的圓心 O 始終落在 B 上,朝向是 B 上 O 點處的切線方向。隻要圓 A 繞 B 一周,就形成了一個環面。如下圖所示,紅色的就是圓 A,黑色的就是圓 B。

用 Mathematica 玩轉環面

為不失一般性,不妨假設紅圓的半徑是 r,其圓心在黑圓上的點 (R Cos[u], R Sin[u], 0) 處。該怎麼才能畫出紅圓呢?我們需要知道此時紅圓的"局部标架",也就是上圖中綠色部分的三個箭頭代表的三個機關向量。垂直向上的箭頭很好辦,就是 (0, 0, 1);垂直于紅圓,也就是往裡的那個箭頭不影響繪制紅圓可以不管;而剩下的朝右的那個箭頭和圓心是共線的,是以就是 (Cos[u], Sin[u], 0)。于是假設紅圓的參數為 v,可計算其參數方程如下:

圓心坐标+上箭頭向量 r sin(v)+右箭頭向量 r cos(v)

用 Mathematica 玩轉環面

用 Mathematica 計算化簡

用 Mathematica 玩轉環面

于是我們定義環面參數方程函數如下。說明一下這個函數還有個可選的設定 L 用于控制環面在 z 軸方向的拉伸程度。預設就是 1,放在這裡主要是為了繪制某種曲面時能複用這部分代碼,省得重新定義計算。

用 Mathematica 玩轉環面

這個函數定義有點特别,設定好 R、r、L 後傳回的是 Function,一個代表曲面的向量值函數。傳回的函數有兩個參數 u 和 v:u 從 0 到 2\[Pi] 的話,就相當于繞大圓一圈,而 v 從 0 到 2\[Pi],則相當于繞小圓一圈。u、v 彼此獨立,則互相交織形成了環面。可以用 ParametricPlot3D 把它畫出來,就是一個甜甜圈的樣子:

用 Mathematica 玩轉環面

02

變化環面

我們得到了環面的參數方程,并把它畫了出來,從視覺方面驗證了這個方程的正确性。下面我們就可以在之前計算的基礎上,變換花樣了。

用 Mathematica 玩轉環面

改變環繞曲線

前文說了,環面是一個圓 A 繞另一個圓 B 形成的曲面,但 A 和 B 隻要拓撲上還是個圓,也就是自身不相交的閉合曲線,那麼這麼繞圈操作之後,拓撲上得到的就還是一個環面。這裡我們考慮一種特殊的曲線:内擺線。内擺線定義如下,它将是我們這一節讨論的,不同于圓的環繞曲線。

用 Mathematica 玩轉環面

在這一小節,我們隻讨論改變 A 的情形,下一節“環面上的曲線”會讨論推廣的改變 B 的情形。現在我們就定義一個可以任意指定環繞曲線 A 的環面函數:

用 Mathematica 玩轉環面

這個定義和 torusSurface 十分相似,無非是把 r Cos[v] 換成 c[[1]],把 r Sin[v] 換成 c[[2]] 而已。接下來我們把橫截面曲線和對應生成的環面對比的繪制出來,環面隻繪制出了四分之三,空出一角并加了厚度,讓橫截面更加清晰可辨。

用 Mathematica 玩轉環面

從定義和上面幾幅圖可以看到,閉合曲線 A 在環繞過程中并不發生變化。注意内擺線的形狀都是某種正 k 邊形,我們可以考慮讓 A 在環繞過程中自身繞中心旋轉,隻要旋轉速率适當,就可以在環繞一周後,仍然形成閉合曲面。經過一番思考,可以把這個想法寫成如下函數:

用 Mathematica 玩轉環面

這個函數裡的 k 表示了截面是正 k 邊形,n 則表示自身旋轉扭曲的程度,相比原來多旋轉了 n/k 圈。下圖展示了 k 分别為 3、4、5 時的環面:

用 Mathematica 玩轉環面

再來一張固定 k 為 3,n 分别為 1、2、3 時的環面,從頂部看:

用 Mathematica 玩轉環面

我們構造的當 k = 3、n = 1 時的扭曲環面,和雕塑家 Helaman Ferguson 的著名作品“Umbilic Torus SC”的整體形狀相當一緻:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

改變表面起伏

對于環面上任意一點,都存在一個平面剛好和環面相切,我們稱之為環面在這一點的切平面。垂直于切平面的機關向量稱之為環面在這一點的法向量,垂直于平面的法向量有兩個,一個朝上一個朝下。環面是一個閉曲面,把空間劃分成了内外兩部分,是以環面上一點的兩個法向量可以說一個朝裡一個朝外。讓環面沿着其法向量的方向有規律的起伏,可以形成一些有趣的形狀。

從法向量的定義可以知道,要計算法向量,關鍵在于計算切平面,而環面上一點切平面則取決于該點上兩個不共線的切向量。我們的環面參數方程可以看作二進制向量函數,它的兩個一階偏導數剛好就可以用作切向量,它們叉積的方向就是該點上一個法向量的方向,改變叉積順序就能得到相反方向。我們可以适當選擇叉積順序來得到朝外的法向量,以友善後續計算。

利用 Mathematica 的符号好計算功能,我們很容易得到環面上法向量的公式,計算很直接,求偏導數,求叉積,然後在歸一化,因為法向量是機關向量。

用 Mathematica 玩轉環面

據此我們可以定義環面上的法向量函數如下:

用 Mathematica 玩轉環面

然後我們就可以定義不同的 “起伏函數” 來改變環面的形狀了。起伏函數是一個标量函數,表示沿法向量起伏的高度就可以了。新形狀參數式總是這樣的:環面 + 起伏 * 法向量

下面我們舉幾個例子,首先可以讓環面沿被環繞的大圓的方向漲縮,定義起伏函數如下,m 表示起伏高度,num 表示漲縮次數:

用 Mathematica 玩轉環面

我們也可以讓環面長出一些尖刺:

用 Mathematica 玩轉環面

更有意思的是,我們可以給上述計算再添加一個參數 t,根據不同的 t 生成不同的圖像,然後輸出成動畫。特别是我們可以精心挑選 t 的範圍,讓這個動畫能夠首尾平滑連接配接,形成無限循環的 GIF 動畫效果。下面就是在尖刺圓環的起伏函數的 v 方向,即環繞的小圓方向上加上參數 t,形成一種不斷吞噬的效果:

用 Mathematica 玩轉環面

然後輸出成 GIF 動圖:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

上圖的尖刺分布有點太過“平實”了,我們還可以定義一個新的起伏函數,讓尖刺能夠交錯分布:

用 Mathematica 玩轉環面

然後一樣我們可以生成動圖:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

上面定義的兩個起伏函數都不小于零,可以說有起無伏,為了讓起伏函數名副其實,我們再定義一個,看看效果:

用 Mathematica 玩轉環面

環面上的曲線

用 Mathematica 玩轉環面

橫向彈簧

之前的計算裡,我們都用了 u、v 兩個互相獨立的參數來生成曲面。如果它們不是互相獨立的會怎麼樣呢?單個參數會生成曲線,而由于我們用環面函數做基礎,那麼很大可能我們得到的是環面上的曲線。這就來試試看好了:

用 Mathematica 玩轉環面

這看起來就像是一圈彈簧,為什麼是這個形狀呢?這是可以解釋的:前面環面函數 torusSurface[R, r][u, v] 中,u、v 彼此獨立互相交織,形成環面。現在不是獨立的了,u 繞大圓的同時,v 以 9 倍于 u 的速度繞小圓,這不就形成螺旋了嘛。上面把 v 固定成 9u 得到的是很均勻的"彈簧"形狀,未免有點無趣,我們可以把 v 變成更加複雜的關于 u 的函數,再加上和之前類似的添加額外參數 t 的技術,就可以得到比較有意思的動畫了:

用 Mathematica 玩轉環面

動畫雖然有趣,但光這樣的線條還是有些單調了,我們可以把它變成管狀。這就是我們之前提到的用圓 A 繞圓 B,但現在 B 不再是一個圓的情形。所用的方法和一開始我們從圓得到環面是一樣的:找到沿着曲線的一個局部标架,然後就可以得到參數方程了。幸運的是,微分幾何中提供了空間曲線一種局部标架:Frenet 标架。要計算這種标架,先要知道的是曲線的一階和二階導數,這可以說是 Mathematica 的強項:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

有了一階和二階導數就可以得到組成 Frenet 标架的三個機關向量,進而定義上述"彈簧"管狀版本的函數:

用 Mathematica 玩轉環面

我們用和之前相似的做法,可以到的上述管狀曲線的 GIF 動畫:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

縱向彈簧

還可以交換一下 u 和 9u 的位置,曲線變成小圓旋轉一圈時,大圓旋轉了九圈,這樣就是一個縱向的彈簧了,而且由于環面的關系,這個彈簧是内外兩層連在一起形成的。為了美觀,我們拉伸了環面 Z 方向的高度。

用 Mathematica 玩轉環面

動畫效果也還不錯:

用 Mathematica 玩轉環面

然後我們仍然可以得到一個管狀版本,并輸出動畫:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面
用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

上述的計算過程非常繁瑣,運作速度比較慢,我用這種方法隻是為了展示"管狀化?imageView2/2/w/1620"的數學原理。Mathematica 裡提供了一個 Tube 函數,可以把折線、曲線"管狀化",我們用它的話速度會非常快,直接計算曲線上的 1000 個點,然後用 Tube 轉換成管狀:

用 Mathematica 玩轉環面
用 Mathematica 玩轉環面

環面扭結

前面的兩個例子展現了曲線 torusSurface[R, r][u, 9u] 和 torusSurface[R, r][9u, u] 兩種情況,如果最後的參數是一般性的 [n*u, m*u] 會是什麼樣子呢?當 n 和 m 互素時,我們得到的是一大類紐結,叫做"環面紐結"。下面就用 Tube 展示了幾種環面紐結:

用 Mathematica 玩轉環面

從頂部看這些環面紐結是這個樣子的:

用 Mathematica 玩轉環面

進一步推廣

我們最後再舉一個例子。著名的荷蘭畫家 Escher 有一幅版畫 Spirals,可以看作四條螺旋帶組成的,不斷縮小小圓半徑的環面:

用 Mathematica 玩轉環面

我們隻要讓環面函數 torusSurface[R, r][u, v] 裡的 r 随着 u 不斷變化,同時限制 v 的變化範圍,就能生成一條螺旋帶,然後把四條這樣的螺旋帶放在一起,就可以構造出和 Spirals 裡極為相似的圖形了。這裡我們再次用到了 ParametricPlot3D 裡的 PlotTheme->"ThickSurface" 選項,讓曲面帶有厚度:

用 Mathematica 玩轉環面

在環面上能做的變化還有很多很多,限于篇幅這裡就不繼續列舉下去了。希望目前為止的這些展示能讓讀者有所啟發,有興趣的讀者可以進一步繼續探索其它可能的變化。

END