OpenSCAD 使用者手冊/其他語言特性
特殊變數提供了一種向模組和函式傳遞引數的替代方法。所有以 '$' 開頭的使用者定義或 OpenSCAD 定義的變數都是特殊變數,類似於 lisp 中的特殊變數。模組和函式除了作為引數傳遞或在內部定義的變數之外,還會看到所有外部變數。
目前有效的特殊變數名只能由 $ 後面跟著簡單字元和下劃線 [a-zA-Z0-9_] 組成,不允許使用高 ASCII 或 Unicode 字元。
常規變數的值在編譯時分配,因此對於所有呼叫來說都是靜態的。
特殊變數從呼叫模組或函式的範圍 (參見變數範圍) 中傳遞其值。這意味著特殊變數在每次呼叫模組或函式時可能具有不同的值。
regular = "regular global";
$special = "special global";
module show() echo(" in show ", regular," ", $special );
echo (" outside ", regular," ", $special );
// ECHO: " outside ", "regular global", " ", "special global"
for ( regular = [0:1] ){ echo("in regular loop ", regular," ", $special ); show();}
// ECHO: "in regular loop ", 0, " ", "special global"
// ECHO: " in show ", "regular global", " ", "special global"
// ECHO: "in regular loop ", 1, " ", "special global"
// ECHO: " in show ", "regular global", " ", "special global"
for ( $special = [5:6] ){ echo("in special loop ", regular," ", $special ); show();}
// ECHO: "in special loop ", "regular global", " ", 5
// ECHO: " in show ", "regular global", " ", 5
// ECHO: "in special loop ", "regular global", " ", 6
// ECHO: " in show ", "regular global", " ", 6
show();
// ECHO: " in show ", "regular global", " ", "special global"
當需要將多個引數透過多層模組呼叫傳遞時,這很有用。
OpenSCAD 已經定義了幾個特殊變數。
特殊變數 $fa、$fs 和 $fn 控制用於生成圓弧的面數
$fa 是片段的最小角度。即使是巨大的圓圈,其片段數也不會超過 360 除以這個數字。預設值為 12(即,一個完整的圓圈有 30 個片段)。允許的最小值為 0.01。嘗試設定更低的值會導致警告。
$fs 是片段的最小尺寸。預設值為 2,因此非常小的圓圈的片段數少於使用 $fa 指定的片段數。允許的最小值為 0.01。嘗試設定更低的值會導致警告。
$fn 是片段數,通常預設值為 0。當此變數的值大於零時,另外兩個變數會被忽略,並且使用此片段數渲染完整的圓圈。
片段數越多,消耗的記憶體和 CPU 就越多;較大的值可能會使許多系統不堪重負。根據設計,$fn 值以及 $fa 和 $fs 的相應結果應該保持較小,至少在設計最終確定之前,可以增加最終結果的值。不建議將 $fn 設定為 128 以上,或者只在特定情況下使用,建議將其設定為 50 以下以提高效能。
您也可以在預覽和渲染時使用兩個不同的值
$fn = $preview ? 32 : 64;
提示: 如果您想建立一個具有軸對齊整數邊界框的圓圈/圓柱體/球體(即,邊界框具有整數尺寸和整數位置),請使用可以被 4 整除的 $fn 值。圓形形狀顯示為內接在提供的半徑或直徑內的多面體。
當使用 $fa 和 $fs 確定圓圈的片段數時,OpenSCAD 從未使用少於 5 個片段。
這是計算圓圈中片段數的 C 程式碼
int get_fragments_from_r(double r, double fn, double fs, double fa)
{
if (r < GRID_FINE) return 3;
if (fn > 0.0) return (int)(fn >= 3 ? fn : 3);
return (int)ceil(fmax(fmin(360.0 / fa, r*2*M_PI / fs), 5));
}
或者,您也可以將此 OpenSCAD 版本嵌入您的程式碼中,以瞭解發生了什麼,您需要將 r= 設定為您的尺寸
echo(n=($fn>0?($fn>=3?$fn:3):ceil(max(min(360/$fa,r*2*PI/$fs),5))),a_based=360/$fa,s_based=r*2*PI/$fs);
球體首先被切成與渲染球體半徑的圓圈所使用的片段數一樣多的切片,然後每個切片都渲染成所需數量的片段,以滿足切片半徑。您可能已經意識到,球體的極點通常是五邊形。這就是原因。
圓柱體的片段數使用兩個半徑中較大的一個確定。
該方法還用於渲染來自 DXF 檔案的圓圈和圓弧。匯入 STL 檔案時,這些變數無效。
您可以透過在例項化模組中重置 $fX 值來生成高解析度球體
$fs = 0.01;
sphere(2);
或者,您可以簡單地將特殊變數作為引數傳遞
sphere(2, $fs = 0.01);
您甚至可以縮放特殊變數,而不是重置它
sphere(2, $fs = $fs * 0.01);


變數 $t 用於 "rotate" 和 "translate" 進行動畫,$t*360 表示完整的迴圈。要開始動畫,請選擇 **視窗\動畫** 並在 "FPS" 和 "步驟" 中輸入值。欄位 "時間" 顯示 $t 的當前值,它是一個小數。
變數 $t 的值將從 0 重複到 (1 - 1/步驟)。它永遠不會達到 1,因為這會導致動畫在使用它進行旋轉時出現 "卡頓" -- 兩個連續的幀將處於相同的角度。
沒有變數可以區分動畫執行在第一幀 ($t=0) 和動畫未執行的情況下,因此請將 $t=0 設定為模型的靜止位置。
translate ([0, 0, 10*sin($t*360)])
sphere(2);
使球體在 Z 軸上 -10 和 +10 之間振盪。
rotate ([0, 0, $t*360])
square(5);
圍繞 Z 軸使正方形繞一個角旋轉。要使正方形圍繞其中心旋轉,請使用
rotate ([0, 0, $t*360])
square(5, center=true);
動畫中的所有部分在相同的時間 $t 內完成一個運動週期,跳回零,然後重新開始。但是,可以為週期設定不同的步數,以在同一個動畫中呈現不同速度的錯覺。這可以用來製作不同尺寸的齧合齒輪的動畫。
rotate([0, 0, $t*360/17])
gear(teeth=17);
和
rotate([0, 0, -$t*360/31])
gear(teeth=31);
rotate ([0, 0, $t*360])
translate ([10, 0])
square(5, center=true);
rotate ([0, 0, $t*360])
translate ([9, 0])

rotate ([0, 0, -$t*360])
square(5, center=true);
橢圓軌道
[edit | edit source]translate([10*sin($t*360), 20*cos($t*360)])
square(2, center=true);
請注意,使用“translate”時,物件不會旋轉。
橢圓運動
[edit | edit source]
e=10;
rotate([0, 0, $t*360])
translate([e, 0])
rotate([0, 0, -$t*720])
square([2*e, 2], center=true);
如果選中“Dump Pictures”,則影像將建立在與 .scad 檔案相同的目錄中。匯出的 PNG 檔案可以透過命令列轉換為 gif
convert -delay 10 -loop 0 *.png myimage.gif
其中 -delay 10 是每幀的持續時間(以毫秒為單位),-loop 0 指定迴圈次數(0 = 永遠迴圈)。
Linux convert 命令是 ImageMagick 的一部分,也可以安裝在 macOS 和 Windows 上。可以新增其他引數用於裁剪和縮放。
視口:$vpr、$vpt、$vpf 和 $vpd
[edit | edit source]這些包含當前視口旋轉和平移以及相機距離 - 在進行渲染時。移動視口不會更新它們。在動畫期間,它們會為每幀更新。
- $vpr 顯示旋轉
- $vpt 顯示平移(即不會受到旋轉和縮放的影響)
- $vpf 顯示視點的 FOV(視場) [注意: 需要版本 2021.01]
- $vpd 顯示相機距離 [注意: 需要版本 2015.03]
示例
cube([10, 10, $vpr[0] / 10]);
這使得立方體的大小根據視角而改變,如果動畫迴圈處於活動狀態(不需要使用 $t 變數)
您也可以在改變視角時讓複雜模型的某些部分消失。
所有四個變數都是可寫的,但只有主檔案頂層的賦值才會影響視口。 [注意: 需要版本 2015.03]
示例
$vpr = [0, 0, $t * 360];
這允許在動畫模式下圍繞 Z 軸進行簡單的 360 度旋轉。
選單命令 Edit - Paste Viewport Rotation/Translation 複製當前視口的值,但不復制當前 $vpr 或 $vpt。
執行模式:$preview
[edit | edit source][注意: 需要版本 2019.05]
當在 OpenCSG 預覽(F5)中時,$preview 為真。當在渲染(F6)中時,$preview 為假。
例如,這可以用來在預覽期間減少細節以節省時間,而不會在最終渲染結果中丟失細節
$fn = $preview ? 12 : 72; sphere(r = 1);
請注意,渲染模組不會影響 $preview
render(){
$fn = $preview ? 12 : 72;
sphere(r = 1);
}
另一個用途可能是讓預覽顯示一個裝配檢視,而渲染只生成用於列印的列印零件佈局。
如果列印零件需要額外的功能,例如懸空孔的支撐,則預覽可以省略這些功能,以顯示後處理後的完成零件。
當從命令列執行 OpenSCAD 時,$preview 僅在使用 OpenCSG 生成 PNG 影像時為真。它在使用 CGAL 生成 STL、DXF 和 SVG 檔案時為假。它在生成 CSG 和 ECHO 檔案時也為假。這可能就是你想要的,也可能不是,但你總是可以用 -D 選項在命令列中覆蓋它,就像任何其他變數一樣。
回顯模組
[edit | edit source]echo() 模組將內容列印到編譯視窗(也稱為控制檯)。對於除錯程式碼很有用。另請參見 String 函式 str()。
數值將四捨五入到 5 位有效數字。
使用“variable=variable”作為表示式來輕鬆標記變數非常方便,請參見下面的示例。
用法示例
my_h=50;
my_r=100;
echo("This is a cylinder with h=", my_h, " and r=", my_r);
echo(my_h=my_h,my_r=my_r); // shortcut
cylinder(h=my_h, r=my_r);
在控制檯中顯示為
ECHO: "This is a cylinder with h=", 50, " and r=", 100 ECHO: my_h = 50, my_r = 100
請注意,如果使用 str() 轉換為字串,輸出將不會有額外的雙引號和逗號。
舍入示例
[edit | edit source]舍入的示例
a=1.0;
b=1.000002;
echo(a);
echo(b);
if(a==b){ //while echoed the same, the values are still distinct
echo ("a==b");
}else if(a>b){
echo ("a>b");
}else if(a<b){
echo ("a<b");
}else{
echo ("???");
}
在控制檯中顯示為
ECHO: 1 ECHO: 1 ECHO: "a<b"
小數和大數
[edit | edit source]c=1000002;
d=0.000002;
echo(c); //1e+06
echo(d); //2e-06
HTML
[edit | edit source]HTML 輸出沒有官方支援,但是根據 OpenSCAD 版本,某些 HTML 標籤會在控制檯視窗中渲染。
Echo 函式
[edit | edit source][注意: 需要版本 2019.05]
Echo 可在表示式上下文中使用,以在函式/表示式求值時列印資訊。輸出在表示式求值之前生成,以便允許除錯遞迴函式。
示例
a = 3; b = 5; // echo() prints values before evaluating the expression r1 = echo(a, b) a * b; // ECHO: 3, 5 // using let it's still easy to output the result r2 = let(r = 2 * a * b) echo(r) r; // ECHO: 30 // use echo statement for showing results echo(r1, r2); // ECHO: 15, 30
一個更復雜的示例顯示瞭如何在遞迴函式的下降和上升路徑中使用 echo()。result() 輔助函式是一種在求值後輸出表達式值的方法。
列印遞迴 sum() 的輸入值和結果的示例
v = [4, 7, 9, 12];
function result(x) = echo(result = x) x;
function sum(x, i = 0) = echo(str("x[", i, "]=", x[i])) result(len(x) > i ? x[i] + sum(x, i + 1) : 0);
echo("sum(v) = ", sum(v));
// ECHO: "x[0]=4"
// ECHO: "x[1]=7"
// ECHO: "x[2]=9"
// ECHO: "x[3]=12"
// ECHO: "x[4]=undef"
// ECHO: result = 0
// ECHO: result = 12
// ECHO: result = 21
// ECHO: result = 28
// ECHO: result = 32
// ECHO: "sum(v) = ", 32
渲染
[edit | edit source]

即使在預覽模式下也強制生成網格。這在某些情況下很有用,例如,當布林運算變得太慢而無法跟蹤時。
Render 也可以用來(通常與凸性結合使用)避免/解決預覽偽影。[1] 另請參見 OpenSCAD 使用者手冊/常見問題解答#為什麼模型的某些部分(例如孔)渲染不正確?
用法示例: (需要描述)
render(convexity = 2) difference() {
cube([20, 20, 150], center = true);
translate([-10, -10, 0])
cylinder(h = 80, r = 10, center = true);
translate([-10, -10, +40])
sphere(r = 10);
translate([-10, -10, -40])
sphere(r = 10);
}
表面
[edit | edit source]Surface 從文字或影像檔案讀取 高度圖 資訊。
引數
- 檔案
- 字串。包含高度圖資料的檔案的路徑。
- 中心
- 布林值。這決定了生成的物體的定位。如果為真,則物體在 X 軸和 Y 軸上居中。否則,物體將放置在正象限中。預設為假。
- 反轉
- 布林值。反轉匯入影像的顏色值如何轉換為高度值。在匯入文字資料檔案時,這沒有影響。預設為假:使用此引數產生的幾何體將以其頂部位於 z = 0 平面處的位置定位。在高度圖下方自動新增一個厚度為一個單位的薄“佔位”層。:: [注意: 需要版本 2015.03]
- 凸性
- 整數。凸度引數指定光線與物體相交時可能穿過的正面(背面)的最大數量。此引數僅在 OpenCSG 預覽模式下正確顯示物體時需要,對最終渲染沒有影響。
基於文字的高度圖的格式是數字矩陣,表示特定點的海拔高度。行對映在 Y 軸方向,列對映在 X 軸方向,相鄰行和列之間單位增量為 1。數字必須用空格或製表符分隔。以 # 字元開頭的空行和行將被忽略。
[注意: 需要版本 2015.03]
目前只支援 PNG 影像。影像的 Alpha 通道資訊會被忽略,畫素的高度是透過將顏色值轉換為灰度來確定的,使用 sRGB 顏色空間的線性亮度 (Y = 0.2126R + 0.7152G + 0.0722B)。灰度值按比例縮放至 0 到 100 的範圍。
一個厚度為一個單位的薄“足跡”層會自動新增到高度圖下方。
示例 1
//surface.scad surface(file = "surface.dat", center = true, convexity = 5); %translate([0,0,5])cube([10,10,10], center = true);
#surface.dat 10 9 8 7 6 5 5 5 5 5 9 8 7 6 6 4 3 2 1 0 8 7 6 6 4 3 2 1 0 0 7 6 6 4 3 2 1 0 0 0 6 6 4 3 2 1 1 0 0 0 6 6 3 2 1 1 1 0 0 0 6 6 2 1 1 1 1 0 0 0 6 6 1 0 0 0 0 0 0 0 3 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0
結果
示例 2
// example010.dat generated using octave or matlab:
d = (sin(1:0.2:10)' * cos(1:0.2:10)) * 10;
save("-ascii", "example010.dat", "d");
//original surface
surface(file = "example010.dat", center = true, convexity = 5);
//rotated surface
translate(v = [70, 0, 0]) rotate(45, [0, 0, 1]) surface(file = "example010.dat", center = true, convexity = 5);
//intersection
translate(v = [35, 60, 0])
intersection() {
surface(file = "example010.dat", center = true, convexity = 5);
rotate(45, [0, 0, 1]) surface(file = "example010.dat", center = true, convexity = 5);
}
示例 3
[注意: 需要版本 2015.03]
// Example 3a scale([1, 1, 0.1]) surface(file = "smiley.png", center = true);
// Example 3b scale([1, 1, 0.1]) surface(file = "smiley.png", center = true, invert = true);
示例 4
[注意: 需要版本 2015.03]
// Example 4 surface(file = "BRGY-Grey.png", center = true, invert = false);
-
PNG 測試檔案
-
3D 表面
search() 函式是一個通用函式,用於在一個向量、字串或更復雜的列表-列表結構中查詢一個或多個(或所有)值或值的列表的出現位置。
- search( match_value , string_or_vector [, num_returns_per_match [, index_col_num ] ] );
- match_value
- 可以是單個字串值。搜尋迴圈遍歷字串中的字元,並在第二個引數中搜索每個字元。第二個引數必須是字串或列表列表(此第二個情況不推薦)。search 函式不會搜尋子字串。
- 可以是單個數值。
- 可以是值列表。search 函式搜尋列表中的每個項。
- 要搜尋列表或完整字串,請將列表或字串作為單個元素列表提供,例如 ["abc"] 用於搜尋字串 "abc"(請參閱示例 9)或 [[6,7,8]] 用於搜尋列表 [6,7,8]。如果沒有額外的括號,search 將分別搜尋列表中的每個項。
- 如果 match_value 是布林值,則 search 返回 undef。
- string_or_vector
- 要搜尋匹配項的字串或向量。
- 如果match_value是字串,則此引數應為字串,並且字串將搜尋與match_value中的字元匹配的單個字元匹配項
- 如果這是一個列表列表,v=[[a0,a1,a2...],[b0,b1,b2,...],[c0,c1,c2,...],...],則 search 僅檢視子列表的一個索引位置。預設情況下,此位置為 0,因此 search 僅檢視 a0、b0、c0 等。index_col_num 引數會更改搜尋的索引。
- 如果match_value是字串,而此引數是列表列表,則字串的字元將與列表列表中的相應索引條目進行測試。但是,如果任何字元都無法找到匹配項,則會列印警告訊息,並且該返回值將從輸出中排除(如果num_returns_per_match為 1)。這意味著輸出的長度是不可預測的。
- num_returns_per_match(預設值:1)
- 預設情況下,search 僅查詢 match_value 每個元素的一個匹配項,以作為索引列表返回
- 如果 num_returns_per_match > 1,search 將返回一個列表列表,其中包含 match_value 每個元素最多 num_returns_per_match 個索引值。
- 請參閱下面的示例 8。
- 如果 num_returns_per_match = 0,search 將返回一個列表列表,其中包含 match_value 每個元素的所有匹配索引值。
- 請參閱下面的示例 6。
- index_col_num(預設值:0)
- 如上所述,當搜尋列表列表時,search 僅檢視每個子列表的一個索引位置。該索引位置由index_col_num指定。
- 請參閱下面的示例 5,瞭解一個簡單的使用示例。
- 請參閱 OpenSCAD 中包含的example023.scad,瞭解一個可渲染的示例。
| 示例 | 程式碼 | 結果 |
|---|---|---|
|
1 |
|
[0] |
|
2 |
|
[] |
|
3 |
|
[[0,4]] |
|
4 |
|
[[0,4]](另請參閱下面的示例 6) |
示例 5
data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",3] ]; echo(search(3, data)); // Searches index 0, so it doesn't find anything echo(search(3, data, num_returns_per_match=0, index_col_num=1));
輸出
ECHO: [] ECHO: [2, 8]
示例 6:返回每個搜尋向量元素的所有匹配項。
data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];
search("abc", data, num_returns_per_match=0);
返回
[[0,4],[1,5],[2,6]]
示例 7:返回每個搜尋向量元素的第一個匹配項;特殊情況返回向量。
data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];
search("abc", data, num_returns_per_match=1);
返回
[0,1,2]
示例 8:返回每個搜尋向量元素的前兩個匹配項;向量向量。
data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];
search("abce", data, num_returns_per_match=2);
返回
[[0,4],[1,5],[2,6],[8]]
示例 9
lTable2=[ ["cat",1],["b",2],["c",3],["dog",4],["a",5],["b",6],["c",7],["d",8],["e",9],["apple",10],["a",11] ];
lSearch2=["b","zzz","a","c","apple","dog"];
l2=search(lSearch2,lTable2);
echo(str("Default list string search (",lSearch2,"): ",l2));
返回
ECHO: "Default list string search (["b", "zzz", "a", "c", "apple", "dog"]): [1, [], 4, 2, 9, 3]"
// workout which vectors get the results
v=[ ["O",2],["p",3],["e",9],["n",4],["S",5],["C",6],["A",7],["D",8] ];
//
echo(v[0]); // -> ["O",2]
echo(v[1]); // -> ["p",3]
echo(v[1][0],v[1][1]); // -> "p",3
echo(search("p",v)); // find "p" -> [1]
echo(search("p",v)[0]); // -> 1
echo(search(9,v,0,1)); // find 9 -> [2]
echo(v[search(9,v,0,1)[0]]); // -> ["e",9]
echo(v[search(9,v,0,1)[0]][0]); // -> "e"
echo(v[search(9,v,0,1)[0]][1]); // -> 9
echo(v[search("p",v,1,0)[0]][1]); // -> 3
echo(v[search("p",v,1,0)[0]][0]); // -> "p"
echo(v[search("d",v,1,0)[0]][0]); // "d" not found -> undef
echo(v[search("D",v,1,0)[0]][1]); // -> 8
version() 和 version_num() 返回 OpenSCAD 版本號。
- version() 函式以三個數字的向量形式返回 OpenSCAD 版本,例如 [2011, 9, 23]
- version_num() 函式以數字形式返回 OpenSCAD 版本,例如 20110923
$parent_modules 包含例項化堆疊中的模組數量。parent_module(i) 返回例項化堆疊中當前模組上方 i 個級別的模組名稱。堆疊獨立於模組定義的位置。重要的是它們例項化的位置。例如,這可以用於構建 BOM(物料清單)。
示例
module top() {
children();
}
module middle() {
children();
}
top() middle() echo(parent_module(0)); // prints "middle"
top() middle() echo(parent_module(1)); // prints "top"
[注意: 需要版本 2019.05]
另見 斷言(軟體開發)
Assert 評估一個邏輯表示式。如果表示式評估結果為假,則預覽/渲染的生成將停止,並且透過控制檯報告錯誤條件。報告包含表示式的字串表示形式和在 assert 命令中指定的附加字串(可選)。
assert(condition); assert(condition, message);
引數
- 條件
- 表示式。要評估的表示式,作為對斷言的檢查。
- 訊息
- 字串。斷言失敗時輸出的可選訊息。
最簡單的示例是簡單的 assert(false);,例如在一個名為 assert_example1.scad 的檔案中。
cube();
assert(false);
sphere();
// ERROR: Assertion 'false' failed in file assert_example1.scad, line 2
這個示例幾乎沒有用,但簡單的 assert(false); 可以用於應該不可到達的程式碼部分。
一個有用的示例是檢查輸入引數的有效性
module row(cnt = 3){
// Count has to be a positive integer greater 0
assert(cnt > 0);
for (i = [1 : cnt]) {
translate([i * 2, 0, 0]) sphere();
}
}
row(0);
// ERROR: Assertion '(cnt > 0)' failed in file assert_example2.scad, line 3
在編寫庫時,在斷言失敗的情況下向使用者輸出更多資訊可能很有用。
module row(cnt = 3){
assert(cnt > 0, "Count has to be a positive integer greater 0");
for(i = [1 : cnt]) {
translate([i * 2, 0, 0]) sphere();
}
}
row(0);
// ERROR: Assertion '(cnt > 0)': "Count has to be a positive integer greater 0" failed in file assert_example3.scad, line 2
Assert 返回其子節點,因此在函式中使用它時,您可以編寫
function f(a, b) =
assert(a < 0, "wrong a") // assert input
assert(b > 0, "wrong b") // assert input
let (c = a + b) // derive a new value from input
assert(c != 0, "wrong c") // assert derived value
a * b; // calculate
