使用 OpenSCAD CheatSheet


想學習 OpenSCAD,〈OpenSCAD User Manual〉算是個蠻完整的說明,有時間其實應該好好看一下,不過老實說,我也沒有全部看完過,大部份的時間裏,我都是 查詢〈OpenSCAD CheatSheet〉,知道想使用的模組、轉換等如何使用,然後就動手做了…XD

OpenSCAD CheatSheet

在〈Hello, OpenSCAD!〉中看到了基本的 OpenSCAD 程式樣貌,像是變數、for 語法、cubetext 模組、translaterotate 轉換等,這邊就以 OpenSCAD CheatSheet 中的說明來進行。

變數

首先你看到的是變數,其說明是列在〈OpenSCAD CheatSheet〉的 Syntax 區域:

my_text = "Hello, OpenSCAD!";
step_angle = 30;
radius = 30;
height = 5;

乍看沒什麼,就像是個動態定型語言,不需要宣告變數型態,不過,在〈Variable〉 中有這麼一句話:

OpenSCAD is a Functional programming language, as such variables are bound to expressions and keep a single value during their entire lifetime due to the requirements of referential transparency.

由於我一開始是邊做邊學,確實沒有注意到 Functional programming 這件事,也因此在〈挑 戰OpenSCAD迷宮產生器〉時,讓我吃足了苦頭,不過都克服過來了,現在是用得蠻順手的,以後有人問我 Functional programming 可以用在哪,至少我可以舉 OpenSCAD 當作例子了。

不過,說是 Functional programming 語言,還是有些不同,你對同一變數多次設值,是不會產生錯誤,只是同一範圍中,只會有一個值,而同一範圍中,無論你在哪些地方取值,取得的一定是最後一次設定的值。例如:

x = 1;
echo(x); // 顯示 2
x = 2;
echo(x); // 顯示 2

你可以在 OpenSCAD 的環境右下角 Console 看到兩次的 “ECHO: 2”。至於這個行為在〈Variables are set at compile-time, not run-time〉有解釋為什麼,總之,別管這個行為,就照著 Functional programming 的基本概念,變數只能指定值一次,之後就是 Immutable 就是了。

for 迴圈

你看到的 for 迴圈,是列在 〈OpenSCAD CheatSheet〉 的 Other 區域中,在〈For Loop〉的說明中有些範例,看了就明白了。

在〈Hello, OpenSCAD!〉中,看到的是最基本的 for(variable = [start : end]) 形式,會產生 startend 的數字,並指定給 variable, 每次遞增 1,因此…

for (a =[3:5]) {
    echo(a);
}

會在 Console 中看到 3、4、5 的顯示,不過,別以為以下最後會顯示 12:

sum = 0;
for (a =[3:5]) {
    sum = sum + a;
    echo(sum);
}
echo(sum);

實際上的結果最後會顯示 0,該怎麼說?官方說明是說,同一範圍中,一個變數只會有一個值,這對 for 也不例外,也就是說,for 外是一個範圍,因此,對 for 外頭來說,sum 的值一定是剛開始設定的 0,至於 for 中就比較難理解了,比較像是每次都複製出 sum 的值 0,然後加 a 後指定給一個新變數 sum, 因此你會看到的顯示是 3、4、5、0。

好吧!我也覺得以上這說明有點難懂,從 Functional programming 的角度來想或許比較簡單,因為 Functional programming 中是沒有迴圈的,只有遞迴,因此,你可以將 for 看成是一個遞迴的語法糖,會比較好懂,就像是:

module forLoop(range, value) {
    if(range[0] <= range[1]) {
        sum = value + range[0];
        echo(sum);
        forLoop([range[0] + 1, range[1]], value);
    } 
}

sum = 0;
forLoop([3, 5], sum);
echo(sum);

這樣的話,對最後結果會產生 3、4、5、0,也就不感到意外了,至於 module,之後還會說明,現在你可以 暫且將之當成是其他命令式語言中的函式或方法。

3D 模組

在〈Hello, OpenSCAD!〉中一開始看到的 cube 模組,列在〈OpenSCAD CheatSheet〉的 3D 區域,顧名思義,就是建立 3D 物件用的模組,在〈cube〉 說明中,可以看到一些範例,cube 可用來繪製立方體。

最主要的是可以記得兩點:一是當使用陣列指定時,三個數值分別是座標 xyz, 大部份的情況下,總是要指定三個值,畢竟建立正立方體的機會沒那麼多;第二點是可以指定 center = true, 這會讓模型以原點來置中,大部份的 3D 模組,多半可以有這個參數。

你也可以看到,cube 可以有 cube(size = [x,y,z], center = true) 這樣的指定方式,這很方便,因為可以不用管參數順序,只要記得參數名稱,也就是說,cube(center = true, size = [x,y,z]) 也是可以的。

2D 模組

建立文字時使用了 text 模組,這是歸類在〈OpenSCAD CheatSheet〉的 2D 區域,你可以在〈OpenSCAD User Manual/Text〉看到,可以設定的參數還蠻多的,就我目前而言,基本上只用過 textsizefont 這三個參數。

text 參數沒有問題,就是你要指定的文字,不好打出來的特殊字元,也可以使用 Unicode 碼指定,例如:

text("\u20AC 10 \u263A");

這會顯示歐元符號、10 與一個笑臉:

OpenSCAD CheatSheet

size 參數預設是 10,單位是 mm,至於 font 則是字 型名稱,如果你要能建立中文,第一要讓 .scad 檔案是 UTF-8 編碼,第二是要指定中文字型,例如,來個「標楷體」的「春」字:

text("春", font = "標楷體");

這會建立以下的文字:

OpenSCAD CheatSheet

你也可以加粗或者是斜體,方式就如文件中說明的例子之一 font="Liberation Sans:style=Bold Italic",在字型名稱號加上冒號,使用 style 指定 BoldItalic 等。

extrude

上頭說 text 列於 2D 模組,也就是說,即使看起來有厚度,也只是看起來而已,它並不是建立 3D 模型,只是 2D 平面上的一張圖而已,要讓 2D 變 3D,你得進行 extrude 的動作。

在〈Hello, OpenSCAD!〉看到的是 linear_extrude,它歸類於〈OpenSCAD CheatSheet〉的 Other 之中。最基本的當然是給予 2D 一個厚度,成為 3D 物件,像是…

linear_extrude(10) text("春", font = "標楷體");

注意,linear_extrude(10) 之後不用分號,這類輔助某個模組的操作,後頭都是接上某個完成操作的模組。這會建立以下的 3D 模型:

OpenSCAD CheatSheet

轉換

在〈Hello, OpenSCAD!〉看到的 translaterotate,很 簡單,前者以陣列指定 X、Y、Z 座標對模型作平移,後者以陣列指定繞 X、Y、Z 的轉動角度,對模型做旋轉,舉例來說:

translate([-5, -5, -5])
    linear_extrude(10) 
        text("春", font = "標楷體"); 

會讓方才建立的「春」整個以原點置中,結果就是…

OpenSCAD CheatSheet

如果接下來再繞 X 軸轉動 90 度…

rotate([90, 0, 0])
    translate([-5, -5, -5])
        linear_extrude(10) 
            text("春", font = "標楷體");

就會產生以下的結果:

OpenSCAD CheatSheet

你可以看到,rotatetranslatelinear_extrude 連續對一個模組進行操作,中間不用逗號,而我喜歡將它們適當地縮排,因為這會比 rotate([90, 0, 0]) translate([-5, -5, -5]) linear_extrude(10) text("春", font = "標楷體"); 容易讀得多,當然,這類操作多了之後,縮排太多層也是很困擾的,這時可以用自訂模組來處理,這就之後再說明了。