在〈OpenSCAD CheatSheet〉中可以看到,OpenSCAD 在 2D 與 3D 建模上提供的模組並不多,都只是 circle
、square
、sphere
、cube
等基本模組,然而,複雜的模型,就是從這些基本模組透過各種組合、運算而來,在這些運算中,最基本的就是 union
、difference
、intersection
布林運算,以及一個 hull
轉換。
union
在模型的布林運算中,union
是最使用的,也就是取模型的聯集,其實你早就在使用了,隨便舉個例子好了:
radius = 10;
circle(radius, $fn = 48);
translate([0, -radius, 0])
square(radius * 2);
在這個程式中,你建立了一個圓與一個方塊。在幾何計算上,圓基本上可由數段直線組成,這邊使用 $fn
指定這個圓實際上有 48 個邊,接著建立一個方塊,邊長為圓直徑,並在 Y 軸負方向位移一個半徑長,結果就是…
在 OpenSCAD 中,如果沒有特別指定,模型間就是自動進行聯集,然而,有時你會想要將聯集完成的模型,視成單一模型做進一步操作,這有兩個方式可以做到,一是為聯集完成的模型自訂模組,例如:
radius = 10;
module circle_and_square(radius) {
circle(radius, $fn = 48);
translate([0, -radius, 0])
square(radius * 2);
}
rotate(-45)
circle_and_square(radius);
或者是使用 union
明確指明:
radius = 10;
rotate(-45) union() {
circle(radius, $fn = 48);
translate([0, -radius, 0])
square(radius * 2);
}
這兩種方式都可以形成以下的圖案:
如果你聯集完的模型,還不是什麼階段性目標,而不想多費心神為它定義模組,就可以使用 union
。舉個例子來說,建立一個簡單的愛心:
radius = 10;
module heart(radius) {
rotated_angle = 45;
diameter = radius * 2;
$fn = 48;
rotate(-rotated_angle) union() {
circle(radius);
translate([0, -radius, 0])
square(diameter);
}
translate([cos(rotated_angle) * diameter, 0, 0])
circle(radius);
}
heart(radius);
這邊有個簡單的幾何問題,就留給你了,為什麼最後建立的 circle
要位移 cos(rotated_angle) * diameter
才能成為愛心呢?
difference
difference
就是對模型做差集,也就是對模型做減法運算,舉個例子來說,你也許會想在愛心上刻個鏤空字:
radius = 20;
module heart(radius) {
rotated_angle = 45;
diameter = radius * 2;
$fn = 48;
rotate(-rotated_angle) union() {
circle(radius);
translate([0, -radius, 0])
square(diameter);
}
translate([cos(rotated_angle) * diameter, 0, 0])
circle(radius);
}
difference() {
heart(radius);
text("LOVE");
}
由於在建立了愛心上,使用 difference
減去了建立的文字,結果就會是…
intersection
intersection
是做模型的交集,也就是兩個模型間彼此有接觸的部份,才可以保留下來,舉個例子來說,如何做一個球面字呢?你可以用 sphere
建立一大一小的立體球先做 difference
,這樣就會是個空心球,接著,建立一個文字並用 linear_extrude
拉高,與空心球做交集…
character = "A";
font_size = 10;
thickness = 1;
module hollow_sphere(radius, thickness) {
$fn = 48;
inner_radius = radius - thickness;
difference() {
sphere(radius);
sphere(inner_radius);
}
}
module sphere_character(ch, font_size, thickness) {
font_offset = font_size / 2;
intersection() {
hollow_sphere(font_size, thickness);
linear_extrude(font_size * 2)
translate([-font_offset, -font_offset, 0])
text(ch, size = font_size);
}
}
sphere_character(character[0], font_size, thickness);
sphere(font_size - thickness, $fn = 48);
雖說這個程式是在示範 intersection
,不過,也是個 union
、difference
、intersection
的結合範例,許多看似複雜的模型,都是由這些操作建立,而且,就像這個範例中示範的,你應該用 module
適當地封裝每個階段的基本模型,一來程式碼比較容易閱讀,二來這些基本模型,未來都可能用得上。這個程式的結果會是…
hull
hull
是列在〈OpenSCAD CheatSheet〉的 Transformations,乍看不是很清楚它的意義,hull 的意思是「殼」,從這方面來想,就是為你的模型建立一個「殼」,這麼想好了,如果你的模型是 2D,那麼 hull
會為這些模型拉一條繃緊的線圍起來,在線內的就是 hull
建立的模型,例如,底下建立兩個圓:
radius = 10;
circle(radius);
translate([2 * radius, 0, 0])
circle(radius);
模型會長這樣:
接著用 hull
將這兩個模型圍起來:
radius = 10;
hull() {
circle(radius);
translate([2 * radius, 0, 0])
circle(radius);
}
結果就會是:
如果是 3D 模型,那麼 hull
就像是使用一塊繃緊的布包住這些模型,這樣的話,應該就不難理解以下這個程式:
radius = 10;
hull() {
linear_extrude(10)
circle(radius);
linear_extrude(20)
translate([2 * radius, 0, 0])
circle(radius);
}
為什麼會產生這個模型了:
最後來出個題目吧!上頭不是建立了一個愛心嗎?那個愛心底部尖尖的,有沒有辦法建立一個愛心,底部是圓的呢?提示:使用 hull
會比較簡單喔!