前言
我們從小學習的座標系統是直角座標(笛卡兒座標):向右走幾步、向上走幾步,就定義了一個點的位置。這很直覺,但不是描述所有形狀的最佳選擇。
想像你要描述一朵花的花瓣——用直角座標你得寫一堆複雜的方程式,但用極座標,只需要一個簡潔的公式 r = cos(3θ) 就能畫出一朵三瓣的玫瑰。這就是極座標的魅力:它天生適合描述以圓心為中心、具有旋轉對稱性的圖形。
這篇文章會帶你從極座標的基礎開始,一路畫到玫瑰曲線、阿基米德螺線和各種令人驚嘆的數學藝術圖形。
極座標基礎
在極座標系統中,一個點的位置由兩個值決定:
- r(半徑):點到原點的距離
- θ(角度):點相對於正 x 軸的角度
從極座標轉換到直角座標很簡單:
x = r * cos(θ)
y = r * sin(θ)
反過來,從直角座標轉換到極座標:
r = sqrt(x² + y²)
θ = atan2(y, x)
p5.js 中的極座標繪圖模板
以下是一個基本的極座標繪圖框架,後面的所有範例都會基於這個結構:
function setup() {
createCanvas(600, 600);
}
function draw() {
background(30);
translate(width / 2, height / 2);
stroke(255, 80, 80);
strokeWeight(2);
noFill();
beginShape();
for (let theta = 0; theta < TWO_PI; theta += 0.01) {
// 這裡定義 r 與 θ 的關係
let r = 200 * polarFunction(theta);
let x = r * cos(theta);
let y = r * sin(theta);
vertex(x, y);
}
endShape(CLOSE);
}
function polarFunction(theta) {
// 在這裡替換不同的極座標函數
return cos(3 * theta); // 三瓣玫瑰
}
玫瑰曲線 (Rose Curves)
玫瑰曲線是極座標中最經典的美麗圖形。公式非常簡潔:
r = a cos(n θ) 或 r = a sin(n θ)
其中 a 是花瓣的長度,n 決定了花瓣的數量和形狀:
- n 是奇數 → n 片花瓣
- n 是偶數 → 2n 片花瓣
- n 是分數(如 2/3) → 更複雜的圖案,需要多圈才能閉合
玫瑰曲線動畫
let n = 3;
let maxTheta = 0;
function setup() {
createCanvas(600, 600);
background(30);
}
function draw() {
background(30, 12); // 半透明背景產生拖尾
translate(width / 2, height / 2);
// 畫完成的部分
stroke(255, 80, 80);
strokeWeight(2);
noFill();
beginShape();
for (let theta = 0; theta < maxTheta; theta += 0.01) {
let r = 200 cos(n theta);
let x = r * cos(theta);
let y = r * sin(theta);
vertex(x, y);
}
endShape();
// 畫當前的點
let r = 200 cos(n maxTheta);
let x = r * cos(maxTheta);
let y = r * sin(maxTheta);
fill(255);
noStroke();
ellipse(x, y, 8, 8);
// 畫從原點到當前點的半徑線
stroke(255, 255, 255, 60);
line(0, 0, x, y);
// 角度遞增
maxTheta += 0.02;
// 判斷是否完成一個完整圖形
let fullCycle = (n % 2 === 0) ? TWO_PI : PI;
if (maxTheta > fullCycle * 2) {
maxTheta = 0;
n = floor(random(2, 8));
background(30);
}
// 顯示資訊
scale(1);
fill(255);
textSize(16);
text("r = cos(" + n + "θ)", -280, -260);
text("花瓣數: " + (n % 2 === 0 ? 2 * n : n), -280, -235);
}
分數階玫瑰曲線
當 n 不是整數時,事情變得更加有趣:
function draw() {
background(30);
translate(width / 2, height / 2);
let n = 5 / 3; // 分數!
let totalRotations = 3; // 需要轉 3 圈才能閉合
stroke(255, 80, 80);
strokeWeight(1.5);
noFill();
beginShape();
for (let theta = 0; theta < TWO_PI * totalRotations; theta += 0.005) {
let r = 200 cos(n theta);
let x = r * cos(theta);
let y = r * sin(theta);
vertex(x, y);
}
endShape(CLOSE);
fill(255);
noStroke();
textSize(14);
text("r = cos(5/3 · θ)", -280, -260);
text("需要旋轉 3 圈才能閉合", -280, -235);
}
當 n = p/q(最簡分數)時,曲線需要旋轉 q 圈(如果 p 和 q 都是奇數則為 q 的 π 倍)才能閉合。這產生的圖形遠比整數 n 來得複雜和精緻。
阿基米德螺線 (Archimedean Spiral)
阿基米德螺線的公式是:
r = a + b * θ
半徑隨角度線性增長,每一圈之間的距離是固定的。這在自然界中很常見——比如捲起來的繩子、鐘錶的發條。
function setup() {
createCanvas(600, 600);
}
function draw() {
background(30);
translate(width / 2, height / 2);
let a = 0;
let b = 3; // 控制螺線的疏密
stroke(80, 180, 255);
strokeWeight(2);
noFill();
beginShape();
for (let theta = 0; theta < 10 * TWO_PI; theta += 0.02) {
let r = a + b * theta;
let x = r * cos(theta);
let y = r * sin(theta);
vertex(x, y);
}
endShape();
// 對數螺線做比較
stroke(255, 80, 80);
beginShape();
for (let theta = 0; theta < 6 * TWO_PI; theta += 0.02) {
let r = 5 exp(0.1 theta); // 對數螺線
if (r > 300) break;
let x = r * cos(theta);
let y = r * sin(theta);
vertex(x, y);
}
endShape();
fill(80, 180, 255);
noStroke();
textSize(14);
text("藍色:阿基米德螺線 r = bθ", -280, -260);
fill(255, 80, 80);
text("紅色:對數螺線 r = ae^(bθ)", -280, -240);
}
對數螺線(等角螺線)
對數螺線的公式是:
r = a e^(b θ)
和阿基米德螺線不同,對數螺線的每一圈之間距離會按比例增長。它有一個神奇的性質:自相似性——不管你放大多少倍,形狀都一樣。鸚鵡螺的殼就是典型的對數螺線。
蝴蝶曲線 (Butterfly Curve)
這是我最喜歡的極座標曲線之一,由 Temple H. Fay 在 1989 年發表:
r = e^(sin θ) - 2cos(4θ) + sin⁵((2θ - π) / 24)
function setup() {
createCanvas(700, 700);
background(30);
}
function draw() {
background(30);
translate(width / 2, height / 2 + 50);
stroke(255, 160, 80);
strokeWeight(1.5);
noFill();
let scale_ = 80;
beginShape();
for (let theta = 0; theta < 24 * PI; theta += 0.01) {
let r = exp(sin(theta))
- 2 cos(4 theta)
+ pow(sin((2 * theta - PI) / 24), 5);
let x = r cos(theta) scale_;
let y = -r sin(theta) scale_; // 翻轉使蝴蝶朝上
vertex(x, y);
}
endShape();
fill(255);
noStroke();
textSize(14);
text("蝴蝶曲線 (Butterfly Curve)", -100, 290);
}
跑起來你會看到一隻非常精緻的蝴蝶——完全由一條數學曲線畫出來的。
超級公式 (Superformula)
Johan Gielis 在 2003 年提出的超級公式可以用來生成大量自然界的形狀:
r(θ) = ( |cos(m₁θ/4)/a|^n₂ + |sin(m₂θ/4)/b|^n₃ )^(-1/n₁)
let m1, m2, n1, n2, n3;
function setup() {
createCanvas(600, 600);
randomizeParams();
}
function draw() {
background(30);
translate(width / 2, height / 2);
stroke(80, 255, 180);
strokeWeight(2);
noFill();
let sc = 150;
beginShape();
for (let theta = 0; theta <= TWO_PI; theta += 0.005) {
let r = superformula(theta, m1, m2, n1, n2, n3);
let x = r cos(theta) sc;
let y = r sin(theta) sc;
vertex(x, y);
}
endShape(CLOSE);
fill(255);
noStroke();
textSize(13);
text(m1=${m1} m2=${m2}, -280, -260);
text(n1=${nf(n1,1,1)} n2=${nf(n2,1,1)} n3=${nf(n3,1,1)}, -280, -240);
text("點擊更換參數", -280, -215);
}
function superformula(theta, m1, m2, n1, n2, n3) {
let a = 1, b = 1;
let t1 = pow(abs(cos(m1 * theta / 4) / a), n2);
let t2 = pow(abs(sin(m2 * theta / 4) / b), n3);
return pow(t1 + t2, -1.0 / n1);
}
function mousePressed() {
randomizeParams();
}
function randomizeParams() {
m1 = floor(random(1, 10));
m2 = m1; // 通常 m1 = m2
n1 = random(0.5, 20);
n2 = random(0.5, 20);
n3 = random(0.5, 20);
}
透過調整參數,你可以得到圓形、星形、花形、葉形、甚至接近正方形的形狀。Gielis 的論文展示了自然界中的花瓣、海星、貝殼等形狀都能用這個公式近似。
極座標動態藝術:旋轉與漸變
把時間加入極座標函數,就能創造出迷人的動態圖案:
function setup() {
createCanvas(600, 600);
}
function draw() {
background(30, 20);
translate(width / 2, height / 2);
let t = frameCount * 0.01;
for (let layer = 0; layer < 5; layer++) {
let hue = (layer * 60 + frameCount) % 360;
// 用 HSB 模式或自行計算 RGB
let r_col = sin(hue 0.0174) 127 + 128;
let g_col = sin((hue + 120) 0.0174) 127 + 128;
let b_col = sin((hue + 240) 0.0174) 127 + 128;
stroke(r_col, g_col, b_col, 150);
strokeWeight(1.5);
noFill();
let n = 3 + layer; // 不同的花瓣數
let phaseOffset = layer * 0.3;
beginShape();
for (let theta = 0; theta <= TWO_PI; theta += 0.01) {
let r = 50 + layer * 30;
r = (1 + 0.5 cos(n * theta + t + phaseOffset));
let x = r * cos(theta);
let y = r * sin(theta);
vertex(x, y);
}
endShape(CLOSE);
}
}
這段程式碼畫了五層不同的極座標圖形,每層有不同的花瓣數和顏色,隨著時間緩緩旋轉。效果如同一朵在呼吸的彩色花朵。
小結
極座標系統為我們打開了一扇看待形狀的新窗口。當你習慣用「距離和角度」來思考時,很多複雜的圖形突然變得簡單而優雅。玫瑰曲線只需要一行公式,螺線只需要兩個參數,而超級公式則能逼近自然界中幾乎所有的放射對稱形狀。
我鼓勵你拿起這些程式碼,修改參數、混合不同的公式、加入時間變化和色彩——極座標是創意編程中最容易產生「哇」效果的工具之一。
延伸閱讀
- Wolfram MathWorld 上的 Rose Curve 條目
- Daniel Shiffman 的 Coding Challenge #55: Mathematical Rose Patterns
- Johan Gielis 的論文 “A generic geometric transformation that unifies a wide range of natural and abstract shapes”
- 試著用極座標畫出你自己的 Logo 或圖案