前言

我們從小學習的座標系統是直角座標(笛卡兒座標):向右走幾步、向上走幾步,就定義了一個點的位置。這很直覺,但不是描述所有形狀的最佳選擇。

想像你要描述一朵花的花瓣——用直角座標你得寫一堆複雜的方程式,但用極座標,只需要一個簡潔的公式 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 或圖案