OpenSCAD 使用者手冊/條件和迭代函式
評估範圍或向量中的每個值,將其應用於以下操作。
for(variable = [start : increment : end]) for(variable = [start : end]) for(variable = [vector])
引數
- 作為範圍 [ 開始 : <增量 : > 結束 ](參見關於 範圍 的部分)
- 注意:對於範圍,值由冒號分隔,而不是向量中使用的逗號。
- 開始 - 初始值
- 增量 或步長 - 增加值的量,可選,預設 = 1
- 結束 - 當下一個值超過結束時停止
- 示例:
for (a =[3:5])echo(a); // 3 4 5
for (a =[3:0]){echo(a);} // 0 1 2 3 start > end is invalid, deprecated by 2015.3
for (a =[3:0.5:5])echo(a); // 3 3.5 4 4.5 5
for (a =[0:2:5])echo(a); // 0 2 4 a never equals end
for (a =[3:-2:-1])echo(a); // 3 1 -1 negative increment requires 2015.3
be sure end < start
- 作為向量
- 對向量的每個元素評估操作
for (a =[3,4,1,5])echo(a); // 3 4 1 5
for (a =[0.3,PI,1,99]){echo(a);} // 0.3 3.14159 1 99
x1=2; x2=8; x3=5.5;
for (a =[x1,x2,x3]){echo(a);} // 2 8 5.5
for (a =[[1,2],6,"s",[[3,4],[5,6]]])echo(a); // [1,2] 6 "s" [[3,4],[5,6]]
- 向量可以在其他地方描述,例如其他語言中的“for each”
animals = ["elephants", "snakes", "tigers", "giraffes"];
for(animal = animals)
echo(str("I've been to the zoo and saw ", animal));
// "I've been to the zoo and saw elephants", for each animal
for() 是一個運算子。運算子如果包含多個操作,則需要使用大括號 {}。操作以分號結尾,運算子沒有。
for() 並不違反關於變數在一個作用域中只有一個值的規則。每個評估都擁有自己的作用域,允許任何變數具有唯一的價值。不,你仍然不能執行 a=a+1;
請記住,這不是一種迭代語言,for() 不會以程式設計意義上的迴圈方式執行,它會構建一個物件樹,每個範圍/向量中的專案都有一個分支,在每個分支中,“變數”是一個特定的、獨立的例項化或作用域。
因此
for (i=[0:3])
translate([i*10,0,0])
cube(i+1);
產生:[見設計/顯示-CSG-樹選單]
group() {
group() {
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [1, 1, 1], center = false);
}
multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [2, 2, 2], center = false);
}
multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [3, 3, 3], center = false);
}
multmatrix([[1, 0, 0, 30], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [4, 4, 4], center = false);
}
}
}
雖然 group() 是按順序構建的,但 for() 的所有例項都作為獨立的實體存在,它們不會按順序迭代同一部分程式碼。
- 巢狀 for()
雖然巢狀多個 for() 語句是合理的,例如
for(z=[-180:45:+180])
for(x=[10:5:50])
rotate([0,0,z]) translate([x,0,0]) cube(1);
相反,所有範圍/向量都可以包含在同一個 for() 運算子中。
for ( variable1 = <range or vector> , variable2 = <range or vector> ) <do something using both variables>

example for() nested 3 deep
color_vec = ["black","red","blue","green","pink","purple"];
for (x = [-20:10:20] )
for (y = [0:4] )color(color_vec[y])
for (z = [0,4,10] )
{translate([x,y*5-10,z])cube();}
shorthand nesting for same result
color_vec = ["black","red","blue","green","pink","purple"];
for (x = [-20:10:20],
y = [0:4],
z = [0,4,10] )
translate([x,y*5-10,z]){color(color_vec[y])cube();}
- 使用向量向量示例

example 1 - iteration over a vector of vectors (rotation)
for(i = [ [ 0, 0, 0],
[ 10, 20, 300],
[200, 40, 57],
[ 20, 88, 57] ])
{
rotate(i)
cube([100, 20, 20], center = true);
}

example 2 - iteration over a vector of vectors (translation)
for(i = [ [ 0, 0, 0],
[10, 12, 10],
[20, 24, 20],
[30, 36, 30],
[20, 48, 40],
[10, 60, 50] ])
{
translate(i)
cube([50, 15, 10], center = true);
}

example 3 - iteration over a vector of vectors
for(i = [ [[ 0, 0, 0], 20],
[[10, 12, 10], 50],
[[20, 24, 20], 70],
[[30, 36, 30], 10],
[[20, 48, 40], 30],
[[10, 60, 50], 40] ])
{
translate([i[0][0], 2*i[0][1], 0])
cube([10, 15, i[1]]);
}
遍歷範圍或向量中的值,併為每次傳遞建立的每個物件建立 交集。
除了為每次傳遞建立獨立的例項外,標準 for() 還對所有這些例項進行分組,從而建立一個隱式的聯合。intersection_for() 是一種解決方法,因為隱式的聯合會阻止使用標準 for() 和 intersection() 語句的組合來獲得預期的結果。
intersection_for() 使用相同引數,並且工作方式與 For 迴圈 相同,只是消除了隱式的聯合。
| 示例 1 - 遍歷範圍 | ||
intersection_for(n = [1 : 6])
{
rotate([0, 0, n * 60])
{
translate([5,0,0])
sphere(r=12);
}
}
|
| 示例 2 - 旋轉: | ||
intersection_for(i = [ [ 0, 0, 0],
[ 10, 20, 300],
[200, 40, 57],
[ 20, 88, 57] ])
{
rotate(i)
cube([100, 20, 20], center = true);
}
|
執行測試以確定是否應執行子範圍中的操作。
非常重要。你無法更改變數的值。如果你更新了方括號內變數的值,新值將在你退出該作用域後丟失。
if (test) scope1
if (test){scope1}
if (test) scope1 else scope2
if (test){scope1} else {scope2}
- 引數
- 測試:通常是布林表示式,但可以是任何值或變數。
- 參見此處瞭解值的真或假狀態。
- 參見此處瞭解布林運算子和邏輯運算子。
- 不要將賦值運算子 '=' 與等於運算子 '==' 混淆
- 範圍 1:當測試為 true 時要採取的一個或多個操作。
- 範圍 2:當測試為 false 時要採取的一個或多個操作。
- 測試:通常是布林表示式,但可以是任何值或變數。
if (b==a) cube(4);
if (b<a) {cube(4); cylinder(6);}
if (b&&a) {cube(4); cylinder(6);}
if (b!=a) cube(4); else cylinder(3);
if (b) {cube(4); cylinder(6);} else {cylinder(10,5,5);}
if (!true){cube(4); cylinder(6);} else cylinder(10,5,5);
if (x>y) cube(1, center=false); else {cube(size = 2, center = true);}
if (a==4) {} else echo("a is not 4");
if ((b<5)&&(a>8)) {cube(4);} else {cylinder(3);}
if (b<5&&a>8) cube(4); else cylinder(3);
自 2015.03 年起,變數現在可以在任何作用域中分配。請注意,分配僅在定義它們的作用域內有效 - 你仍然不允許將值洩漏到外部作用域。有關更多詳細資訊,請參閱 變數作用域。
- 巢狀 if
if() 部分和 else 部分的作用域都可以包含 if() 語句。這種巢狀可以達到很多深度。
if (test1)
{
scope1 if (test2) {scope2.1}
else {scope2.2}
}
else
{
scope2 if (test3) {scope3.1}
else {scope3.2}
}
當範圍 1 和範圍 2 只包含 if() 語句時,可以刪除外部大括號。
if (test1)
if (test2) {scope2.1}
else {scope2.2}
else
if (test3) {scope3.1}
else {scope3.2}
一種演變是
if(test1) {scope1}
else if(test2) {scope2}
else if(test3) {scope3}
else if(test4) {scope4}
else {scope5}
請注意,else 和 if 是兩個單獨的詞。在遍歷測試鏈時,第一個 true 使用其作用域。所有後續測試都將跳過。
- 示例
if((k<8)&&(m>1)) cube(10);
else if(y==6) {sphere(6);cube(10);}
else if(y==7) color("blue")sphere(5);
else if(k+m!=8) {cylinder(15,5,0);sphere(8);}
else color("green"){cylinder(12,5,0);sphere(8);}
一個使用測試來確定要返回哪個值中的 2 個值的函式。
a = test ? TrueValue : FalseValue ; echo( test ? TrueValue : FalseValue );
- 引數
- 測試:通常是布林表示式,但可以是任何值或變數。
- 參見此處瞭解值的真或假狀態。
- 參見此處瞭解布林運算子和邏輯運算子。
- 不要將賦值 '=' 與等於 '==' 混淆
- TrueValue:當測試為 true 時要返回的值。
- FalseValue:當測試為 false 時要返回的值。
- OpenSCAD 中的值是數字(如 42)、布林值(如 true)、字串(如“foo”)、向量(如 [1,2,3])或未定義值(undef)。值可以儲存在變數中,作為函式引數傳遞,並作為函式結果返回。
- 測試:通常是布林表示式,但可以是任何值或變數。
這類似於?:來自類 C 程式語言家族的運算子。
- 示例
a=1; b=2; c= a==b ? 4 : 5 ; // 5 a=1; b=2; c= a==b ? "a==b" : "a!=b" ; // "a!=b" TrueValue = true; FalseValue = false; a=5; test = a==1; echo( test ? TrueValue : FalseValue ); // false L = 75; R = 2; test = (L/R)>25; TrueValue = [test,L,R,L/R,cos(30)]; FalseValue = [test,L,R,sin(15)]; a1 = test ? TrueValue : FalseValue ; // [true, 75, 2, 37.5, 0.866025]
Some forms of tail-recursion elimination are supported.
支援遞迴函式呼叫。使用條件 "... ? ... : ...",可以確保遞迴被終止。注意:有一個內建的遞迴限制,以防止應用程式崩潰。如果遇到限制,函式將返回 undef。
- 示例
// recursion - find the sum of the values in a vector (array) by calling itself
// from the start (or s'th element) to the i'th element - remember elements are zero based
function sumv(v, i, s = 0) = (i == s ? v[i] : v[i] + sumv(v, i-1, s));
vec=[ 10, 20, 30, 40 ];
echo("sum vec=", sumv(vec, 2, 1)); // calculates 20+30=50
多個巢狀條件可能難以理解。將它們格式化為多行縮排的“if/else”語句會更清晰。
// find the maximum value in a vector
function maxv(v, m=-999999999999, i=0) =
(i == len(v) )
? m
: (m > v[i])
? maxv(v, m, i+1)
: maxv(v, v[i], i+1);
v=[7,3,9,3,5,6];
echo("max",maxv(v)); // ECHO: "max", 9
[已棄用: assign() 將在將來的版本中刪除。現在可以在任何地方分配變數。如果你更喜歡這種設定值的方式,可以使用新的 Let 語句 代替。]
為子樹設定變數的新值。
- 引數
- 應該(重新)分配的變數
- 示例
for (i = [10:50])
{
assign (angle = i*360/20, distance = i*10, r = i*2)
{
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
}
for (i = [10:50])
{
angle = i*360/20;
distance = i*10;
r = i*2;
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
[注意: 需要 2019.05 版本]
將子樹中的變數設定為新值。引數按順序計算,可能互相依賴(與已棄用的 assign() 語句相反)。
- 引數
- 要設定的變數
- 示例
for (i = [10:50])
{
let (angle = i*360/20, r= i*2, distance = r*5)
{
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
}



