黃金螺線

March 7, 2022

如果你想玩玩線條之美,黃金螺線應該是個不錯的入門選擇,若以極座標 (r, θ) 表示的話,黃金螺線的公式是:

黃金螺線

使用公式繪製

其中 φ 是黃金比例 (1 + sqrt(5)) / 2,θ 是徑度,有了公式,可以很快地畫出黃金螺線:

use <polyline_join.scad>
use <util/radians.scad>

phi = (1 + sqrt(5)) / 2;
degrees = 720;

points = [
    for(d = [0:degrees])
    let(
        theta = radians(d),
        r = pow(phi, theta * 2 / PI)
    )
    r * [cos(d), sin(d)]
];

polyline_join(points)
    circle(1);

這會建立以下的圖形:

黃金螺線

費氏數列

黃金螺線另一個常為人所知的事實是跟黃金矩形有關,而黃金矩形又跟費氏數列有關,在維基百科的〈費氏數列〉條目中,有個黃金矩形圖片,其由數個正方形組成,而正方形的邊長關係,就符合費氏數列:

黃金螺線

黃金螺線可以將黃金矩形中每個正方形的兩個對角,使用一個弧連接起來,弧的半徑就是費氏數。例如:

use <polyline_join.scad>
use <arc.scad>
use <shape_square.scad>
use <util/fibseq.scad>

module golden_rectangle(from, to, base_width, line_width) {
    if(from <= to) {
        fibs = fibseq(from, from + 1);
        r = base_width * fibs[0];
        
        // 90 度弧線
        arc(radius = r, 
            angle = 90, 
            width = line_width, 
            width_mode = "LINE_INWARD"
        );
        
        // 正方形
        sq_shape = shape_square(r);
        translate([r, r] / 2)
        polyline_join([each sq_shape, sq_shape[0]])
            circle(line_width / 2);
        
        diff = fibs[1] - fibs[0];
        
        translate([0, -diff * base_width])
	    rotate(90)
            golden_rectangle(from + 1, to, base_width, line_width);
    }
}

$fn = 24;

from = 1;
to = 6;
base_width = 5;
line_width = 2;

linear_extrude(line_width)
    golden_rectangle(from, to, base_width, line_width);

dotSCAD 的 fibseq 可以生成第 from 個到第 to 個費氏數列,畫出來的模型如下:

黃金螺線

怎麼感覺越外圍的弧越不連續?當然,因為使用了固定的 $fn,你要說這是風格也可以,可以試著改變一下 $fn 為較小的值,這會生成有趣的模型:

黃金螺線

結合 dotSCAD

如果不希望 r 越來越大,螺線就看來不連續,可以每次繪製弧線時適當地增加 $fn,或者是透過公式,當螺線的 r 越大時適當地縮小 θ,有興趣可以自己嘗試看看。

沒興趣嘗試的話,可以使用 dotSCAD 的 golden_spiral 函式,它會產生黃金螺線的點,以及相對應的角度:

use <golden_spiral.scad>

pts_angles = golden_spiral(
    from = 3, 
    to = 10, 
    point_distance = 1
);

for(pt_angle = pts_angles) {
    translate(pt_angle[0]) 
        sphere(0.5);
}

從繪製出來的圖案可以看到,golden_spiral 函式產生的點與點間距離,大致上會與 point_distance 近似:

黃金螺線

可藉此避免螺線的 r 越大螺線越不連續的問題,例如:

use <polyline_join.scad>
use <shape_square.scad>
use <golden_spiral.scad>
use <hollow_out.scad>
use <util/fibseq.scad>

// 黃金矩形
module golden_rectangle(from, to, base_width, line_width) {
    if(from <= to) {
        fibs = fibseq(from, from + 1);
        r = base_width * fibs[0];
        
        sq_shape = shape_square(r);
        translate([r, r] / 2)
        polyline_join([each sq_shape, sq_shape[0]])
            circle(line_width / 2);
        
        diff = fibs[1] - fibs[0];
        
        translate([0, -diff * base_width])
	    rotate(90)
            golden_rectangle(from + 1, to, base_width, line_width);
    }
    else {
        // 最後畫個小環
        fibs = fibseq(from - 1, from);
        diff = fibs[1] - fibs[0];
        r = base_width * fibs[0];
        
        ring_r = r / 8;
        
        offset_p = [-r / 2, -diff * base_width - (r + ring_r) + line_width * 0.5];
        rotate(90)
        translate(offset_p)
        hollow_out(line_width)
            circle(ring_r);
    }
}

// 黃金螺線
module golden_spiral(from, to, base_width, line_width, point_distance) {
    pts_angles = golden_spiral(
        from = from, 
        to = to, 
        point_distance = point_distance
    );

    points = [for(pt_angle = pts_angles) pt_angle[0]] * base_width;

    polyline_join(points)
        circle(line_width / 2);
}

$fn = 24;

from = 1;
to = 5;
base_width = 5;
line_width = 1.25;
point_distance = .5;

linear_extrude(line_width * 2) {
    golden_rectangle(from, to, base_width, yline_width);
    golden_spiral(from, to, base_width, line_width, point_distance);
}

我幫這個模型加了個小環,3D 列印後還可以當吊飾:

黃金螺線

分享到 LinkedIn 分享到 Facebook 分享到 Twitter