想學習 OpenSCAD,〈OpenSCAD User Manual〉算是個蠻完整的說明,有時間其實應該好好看一下,不過老實說,我也沒有全部看完過,大部份的時間裏,我都是 查詢〈OpenSCAD CheatSheet〉,知道想使用的模組、轉換等如何使用,然後就動手做了…XD
在〈Hello,
OpenSCAD!〉中看到了基本的 OpenSCAD 程式樣貌,像是變數、for
語法、cube
、text
模組、translate
、rotate
轉換等,這邊就以 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])
形式,會產生 start
到 end
的數字,並指定給 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
可用來繪製立方體。
最主要的是可以記得兩點:一是當使用陣列指定時,三個數值分別是座標 x
、y
、z
,
大部份的情況下,總是要指定三個值,畢竟建立正立方體的機會沒那麼多;第二點是可以指定 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〉看到,可以設定的參數還蠻多的,就我目前而言,基本上只用過 text
、size
與 font
這三個參數。
text
參數沒有問題,就是你要指定的文字,不好打出來的特殊字元,也可以使用 Unicode 碼指定,例如:
text("\u20AC 10 \u263A");
這會顯示歐元符號、10 與一個笑臉:
size
參數預設是 10,單位是 mm,至於 font
則是字
型名稱,如果你要能建立中文,第一要讓 .scad 檔案是 UTF-8
編碼,第二是要指定中文字型,例如,來個「標楷體」的「春」字:
text("春", font = "標楷體");
這會建立以下的文字:
你也可以加粗或者是斜體,方式就如文件中說明的例子之一 font="Liberation Sans:style=Bold
Italic"
,在字型名稱號加上冒號,使用 style
指定 Bold
、Italic
等。
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 模型:
轉換
在〈Hello,
OpenSCAD!〉看到的 translate
與 rotate
,很
簡單,前者以陣列指定 X、Y、Z 座標對模型作平移,後者以陣列指定繞 X、Y、Z 的轉動角度,對模型做旋轉,舉例來說:
translate([-5, -5, -5])
linear_extrude(10)
text("春", font = "標楷體");
會讓方才建立的「春」整個以原點置中,結果就是…
如果接下來再繞 X 軸轉動 90 度…
rotate([90, 0, 0])
translate([-5, -5, -5])
linear_extrude(10)
text("春", font = "標楷體");
就會產生以下的結果:
你可以看到,rotate
、translate
、linear_extrude
連續對一個模組進行操作,中間不用逗號,而我喜歡將它們適當地縮排,因為這會比 rotate([90, 0, 0])
translate([-5, -5, -5]) linear_extrude(10) text("春", font =
"標楷體");
容易讀得多,當然,這類操作多了之後,縮排太多層也是很困擾的,這時可以用自訂模組來處理,這就之後再說明了。