跳轉到內容

OpenSCAD 使用者手冊/OpenSCAD 語言

來自華夏公益教科書,開放世界開放圖書


這是以下內容的列印版本:OpenSCAD 語言 其他所有內容都在 OpenSCAD 使用者手冊/列印版本 中。對於由 [隱藏] 或 [顯示] 控制的內容,您看到的內容就是列印的內容。此訊息不會被列印。



第 1 章 -- 概述

[編輯 | 編輯原始碼]

OpenSCAD 使用者手冊/OpenSCAD 語言

OpenSCAD 是一款基於 函數語言程式設計 語言二維/三維 以及 實體建模 程式,用於建立可在螢幕上預覽並渲染為三維 網格模型,從而允許模型以各種二維/三維檔案格式匯出。

OpenSCAD 語言中的指令碼用於建立二維或三維模型。此指令碼是一個自由格式的行動語句列表。

 object();
 variable = value;
 operator()   action();
 operator() { action();    action(); }
 operator()   operator() { action(); action(); }
 operator() { operator()   action();
              operator() { action(); action(); } }
物件
物件是模型的構建塊,由二維和三維基本體建立。物件以分號 ';' 結尾。
示例:cube()、sphere()、polygon()、circle() 等。
行動
行動語句包括使用基本體建立物件以及為變數賦值。行動語句也以分號 ';' 結尾。
示例:a=1; b = a+7;
運算子
運算子或變換會修改物件的位置、顏色和其他屬性。當運算子的作用域涵蓋多個行動時,運算子使用花括號 '{}'。可以對相同的行動或行動組使用多個運算子。多個運算子從右到左處理,即最靠近行動的運算子先處理。運算子不會以分號 ';' 結尾,但它們包含的各個行動會。
示例
   cube(5);
   x = 4+y;
   rotate(40) square(5,10);
   translate([10,5]) { circle(5); square(4); }
   rotate(60) color("red") { circle(5); square(4); }
   color("blue") { translate([5,3,0]) sphere(5); rotate([45,0,45]) { cylinder(10); cube([5,6,7]); } }

註釋是在指令碼或程式碼中添加註釋的一種方式(無論是為自己還是未來的程式設計師),描述程式碼的工作原理或它做了什麼。編譯器不會評估註釋,也不應使用註釋來描述不言自明的程式碼。

OpenSCAD 使用 C++ 風格的註釋

// This is a comment
  
myvar = 10; // The rest of the line is a comment
  
/*
   Multi-line comments
   can span multiple lines.
*/

值和資料型別

[編輯 | 編輯原始碼]

OpenSCAD 中的值可以是數字(如 42)、布林值(如 true)、字串(如“foo”)、範圍(如 [0: 1: 10])、向量(如 [1,2,3])或未定義值(undef)。值可以儲存在變數中、作為函式引數傳遞以及作為函式結果返回。

[OpenSCAD 是一種動態型別語言,具有固定的資料型別集。沒有型別名稱,也沒有使用者定義的型別。]

數字是 OpenSCAD 中最重要的值型別,它們以其他語言中熟悉的十進位制表示法編寫。例如,-1、42、0.5、2.99792458e+8。[OpenSCAD 不支援數字的八進位制或十六進位制表示法。]

除了十進位制數字外,還定義了以下特殊數字的名稱

  • PI

OpenSCAD 只有一個數字型別,即 64 位 IEEE 浮點數。OpenSCAD 不會將整數和浮點數區分成兩種不同的型別,也不支援複數。由於 OpenSCAD 使用 IEEE 浮點數標準,因此在數學中數字的行為有一些偏差

  • 我們使用二進位制浮點數。分數不會被精確地表示,除非分母是 2 的冪。例如,0.2 (2/10) 在內部沒有精確的表示,但 0.25 (1/4) 和 0.125 (1/8) 被精確地表示。
  • 可表示的最大數字約為 1e308。如果數字結果太大,則結果可以是無窮大(由 echo 列印為 inf)。
  • 可表示的最小數字約為 -1e308。如果數字結果太小,則結果可以是負無窮大(由 echo 列印為 -inf)。
  • 如果數字結果無效,則結果可以是 Not A Number(由 echo 列印為 nan)。
  • 如果非零數字結果過於接近零而無法表示,則如果結果為負,則結果為 -0,否則為 0。零 (0) 和負零 (-0) 由一些數學運算視為兩個不同的數字,並由 'echo' 以不同方式列印,儘管它們比較時相等。

常量 infnan 不被 OpenSCAD 作為數字常量支援,即使您可以計算出以這種方式由 'echo' 列印的數字。您可以使用以下方法定義具有這些值的變數

inf = 1e200 * 1e200;
nan = 0 / 0;
echo(inf,nan);

nan 值是 OpenSCAD 中唯一一個不等於任何其他值的值,包括它自身。雖然可以使用 'x == undef' 來測試一個變數 'x' 是否具有未定義的值,但不能使用 'x == 0/0' 來測試 'x' 是否是 NaN。相反,必須使用 'x != x' 來測試 'x' 是否是 nan。

布林值

[編輯 | 編輯原始碼]

布林值是具有兩種狀態的變數,通常在 OpenSCAD 中表示為 true 和 false。布林變數通常由條件測試生成,並由條件語句 'if()' 使用。條件運算子 '? :',以及由邏輯運算子 !(非)、&&(與)和 ||(或)生成。諸如 if() 之類的語句實際上接受非布林變數,但在布林上下文中,大多數值都被轉換為 true。被視為 false 的值是

  • false
  • 0-0
  • ""
  • []
  • undef

請注意,"false"(字串)、[0](數值向量)、[ [] ](包含空向量的向量)、[false](包含布林值 false 的向量)和 0/0(非數字)都被視為 true。

字串是零個或多個 Unicode 字元的序列。字串值用於在匯入檔案時指定檔名,以及在使用 echo() 時顯示文字以進行除錯。字串也可以與 text() 原語 一起使用,該原語是在 2015.03 版本中新增的。

字串文字寫為用引號 " 括起來的字元序列,例如:""(空字串)或 "this is a string"

要在字串文字中包含 " 字元,請使用 \"。要在字串文字中包含 \ 字元,請使用 \\。以下以 \ 開頭的轉義序列可以在字串文字中使用

  • \" → "
  • \\ → \
  • \t → 製表符
  • \n → 換行符
  • \r → 回車符
  • \x21 → ! - 僅在 \x01 到 \x7f 範圍內有效,\x00 生成空格
  • \u03a9 → Ω - 4 位 Unicode 程式碼點,有關 Unicode 字元的更多資訊,請參見 text()
  • \U01f600 → 😀 - 6 位 Unicode 程式碼點

此行為是自 OpenSCAD-2011.04 以來新增的。您可以使用以下 sed 命令升級舊檔案:sed 's/\\/\\\\/g' non-escaped.scad > escaped.scad

示例

 echo("The quick brown fox \tjumps \"over\" the lazy dog.\rThe quick brown fox.\nThe \\lazy\\ dog.");
  
 result
ECHO: "The quick brown fox jumps "over" the lazy dog. The quick brown fox. The \lazy\ dog." old result ECHO: "The quick brown fox \tjumps \"over\" the lazy dog. The quick brown fox.\nThe \\lazy\\ dog."

範圍由 for() 迴圈children() 使用。它們有 2 種類型

[<start>:<end>]
[<start>:<increment>:<end>]

雖然用方括號 [] 括起來,但它們不是向量。它們使用冒號 : 作為分隔符而不是逗號。

r1 = [0:10];
r2 = [0.5:2.5:20];
echo(r1); // ECHO: [0: 1: 10]
echo(r2); // ECHO: [0.5: 2.5: 20]

應避免無法用二進位制浮點數精確表示的步長值。整數是可以的,分數值只要其分母是 2 的冪也是可以的。例如,0.25(1/4)和 0.125(1/8)是安全的,但應避免 0.2(2/10)。這些步長值的問題是,由於不精確的算術運算,您的範圍可能會有太多或太少的元素。

缺少的 <increment> 預設為 1。[<start>:<end>] 形式的範圍,其中 <start> 大於 <end>,會生成警告,並且等效於 [<end>: 1: <start>]。[<start>:1:<end>] 形式的範圍,其中 <start> 大於 <end>,不會生成警告,並且等效於 []。範圍中的 <increment> 可以為負數(對於 2014 年之後的版本)。

未定義的值

[編輯 | 編輯原始碼]

未定義的值是一個特殊的值,寫為 undef。它是未賦值變數的初始值,並且通常由傳遞非法引數的函式或操作返回。最後,undef 可以用作空值,等效於其他程式語言中的 nullNULL

所有包含 undef 值的算術表示式都計算為 undef。在邏輯表示式中,undef 等效於 false。具有 undef 的關係運算符表示式計算為 false,除了 undef==undef,它為 true

請注意,數值運算也可能返回 'nan'(非數字)以指示非法引數。例如,0/falseundef,但 0/0 是 'nan'。關係運算符(如 < 和 >)如果傳遞非法引數,則返回 false。雖然 undef 是語言值,但 'nan' 不是。

OpenSCAD 變數透過具有名稱或 識別符號 的語句建立,透過表示式賦值,以及分號。在許多命令式語言中找到的陣列的作用在 OpenSCAD 中由向量處理。目前有效的識別符號只能由簡單字元和下劃線 [a-zA-Z0-9_] 組成,不允許使用高 ASCII 或 Unicode 字元。

var = 25;
xx = 1.25 * cos(50);
y = 2*xx+var;
logic = true;
MyString = "This is a string";
a_vector = [1,2,3];
rr = a_vector[2];      // member of vector
range1 = [-1.5:0.5:3]; // for() loop range
xx = [0:5];            // alternate for() loop range

OpenSCAD 是一種 函式式 程式語言,因此 變數 與表示式繫結,並且由於 引用透明度 的要求,在其整個生命週期中保持單個值。在諸如 C 之類的 命令式語言 中,相同行為被視為常量,通常與普通變數形成對比。

換句話說,OpenSCAD 變數更像是常量,但有一個重要的區別。如果變數被多次賦值,則僅最後一個賦值的值在程式碼中的所有位置使用。有關進一步討論,請參見 變數在編譯時設定,而不是在執行時設定。這種行為是由於需要透過使用 -D variable=value 選項在 命令列 上提供變數輸入。OpenSCAD 當前將該賦值放在原始碼的末尾,因此必須允許變數的值發生更改以達到此目的。

值在執行時無法修改;所有變數實際上都是不會改變的常量。每個變數在編譯時保留其最後分配的值,這與 函式式 程式語言一致。與諸如 C 之類的 命令式 語言不同,OpenSCAD 不是一種迭代語言,因此 x = x + 1 的概念是無效的。理解這個概念有助於理解 OpenSCAD 的魅力。

在 2015.03 版本之前,除了檔案頂層和模組頂層之外,無法在任何地方進行賦值。在 if/else  或 for  迴圈中,需要使用 assign()。

自 2015.03 版本以來,變數現在可以在任何範圍內賦值。請注意,賦值僅在定義的範圍內有效——您仍然不允許將值洩露到外部範圍。有關更多詳細資訊,請參見 變數的範圍

a=0;
if (a==0) 
  {
 a=1; //  before 2015.03 this line would generate a Compile Error
      //  since 2015.03  no longer an error, but the value a=1 is confined to within the braces {}
  }

未定義的變數

[編輯 | 編輯原始碼]

未賦值的變數具有特殊值 undef。它可以在條件表示式中進行測試,並由函式返回。

 Example
  
 echo("Variable a is ", a);                // Variable a is undef
 if (a==undef) {
   echo("Variable a is tested undefined"); // Variable a is tested undefined
 }

變數的範圍

[編輯 | 編輯原始碼]

當諸如 translate() 和 color() 之類的運算子需要包含多個動作(動作以 ; 結束)時,需要使用花括號 {} 來對動作進行分組,從而建立一個新的內部範圍。當只有一個分號時,花括號通常是可選的。

每一對花括號在使用它們建立的範圍內建立一個新的範圍。自 2015.03 版本以來,可以在此新範圍內建立新變數。可以向在外部範圍建立的變數賦予新值。這些變數及其值也對在此範圍內建立的更深層的內部範圍可用,但對該範圍外部的任何內容不可用。變數仍然只保留在一個範圍內分配的最後一個值。

                       // scope 1
 a = 6;                // create a
 echo(a,b);            //                6, undef
 translate([5,0,0]){   // scope 1.1
   a= 10;
   b= 16;              // create b
   echo(a,b);          //              100, 16   a=10; was overridden by later a=100;
   color("blue") {     // scope 1.1.1
     echo(a,b);        //              100, 20
     cube();
     b=20;
   }                   // back to 1.1
   echo(a,b);          //              100, 16
   a=100;              // override a in 1.1
 }                     // back to 1   
 echo(a,b);            //                6, undef
 color("red"){         // scope 1.2
   cube();
   echo(a,b);          //                6, undef
 }                     // back to 1
 echo(a,b);            //                6, undef
  
 //In this example, scopes 1 and 1.1 are outer scopes to 1.1.1 but 1.2 is not.
匿名範圍不被視為範圍
 {
   angle = 45;
 }
 rotate(angle) square(10);

For() 迴圈不是變數在一個範圍內只有一個值的規則的例外。迴圈內容的副本是為每個迭代建立的。每個迭代都有自己的範圍,允許任何變數在該迭代中具有唯一的值。不,您仍然不能執行 a=a+1;

變數在編譯時設定,而不是執行時

[編輯 | 編輯原始碼]

因為 OpenSCAD 在編譯時計算變數值,而不是在執行時,所以一個作用域內最後一次變數賦值會應用於該作用域或其內部作用域的任何地方。可以將它們視為可覆蓋的常量,而不是變數。

// The value of 'a' reflects only the last set value
   a = 0;
   echo(a);  // 5
   a = 3;
   echo(a);  // 5
   a = 5;

雖然這看起來違反直覺,但它允許你做一些有趣的事情:例如,如果你將共享庫檔案設定為在根級別定義變數作為預設值,當你將該檔案包含在自己的程式碼中時,你可以透過簡單地為它們賦值來“重新定義”或覆蓋這些常量。因此,改變常量值可以讓你更加靈活。如果常量永遠不會改變,當然,你總是可以確定擁有你在任何常量定義中看到的那個值。這裡不是這樣。如果你在任何其他地方看到一個常量值的定義,它的值可能是不同的。這是非常靈活的。

前面的描述似乎與截至 2022 年 5 月 23 日的 OpenSCAD 行為有所不同。在那個日期,執行上面的例子會導致以下輸出

警告:a 在 “Untitled” 檔案的第 1 行被賦值,但在 “Untitled” 檔案的第 3 行被覆蓋。執行已中止

特殊變數

[編輯 | 編輯原始碼]

特殊變數提供了一種將引數傳遞給模組和函式的替代方法。所有以“$”開頭的變數都是特殊變數,類似於 Lisp 中的特殊變數。因此,它們比普通變數更動態。(有關更多詳細資訊,請參閱其他語言特性

向量或列表是零個或多個 OpenSCAD 值的序列。向量是數值或布林值、變數、向量、字串或其任意組合的集合。它們也可以是表示式,這些表示式計算為其中之一。向量處理了許多命令式語言中陣列的角色。這裡的資訊也適用於使用向量作為其資料的列表和表格。

向量有方括號,[] 包含零個或多個專案(元素或成員),用逗號分隔。向量可以包含向量,向量可以包含向量,等等。

示例

   [1,2,3]
   [a,5,b]
   []
   [5.643]
   ["a","b","string"]
   [[1,r],[x,y,z,4,5]]
   [3, 5, [6,7], [[8,9],[10,[11,12],13], c, "string"]
   [4/3, 6*1.5, cos(60)]

在 OpenSCAD 中使用

  cube( [width,depth,height] );           // optional spaces shown for clarity
  translate( [x,y,z] )
  polygon( [ [x0,y0],  [x1,y1],  [x2,y2] ] );

向量是透過寫入元素列表、用逗號分隔、並用方括號括起來建立的。變數會被其值替換。

  cube([10,15,20]);
  a1 = [1,2,3];
  a2 = [4,5];
  a3 = [6,7,8,9];
  b  = [a1,a2,a3];    // [ [1,2,3], [4,5], [6,7,8,9] ]  note increased nesting depth

向量可以使用包含在方括號中的 for 迴圈進行初始化。

以下示例使用長度為 n 的 10 個值將 result 向量初始化為 a 的值。

n = 10
a = 0;

result = [ for (i=[0:n-1]) a ];
echo(result); //ECHO: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

以下示例顯示了一個長度為 n 的 10 個值的 result 向量,其值分別初始化為 ab,如果索引位置 i 是偶數或奇數。

n = 10
a = 0;
b = 1;
result = [ for (i=[0:n-1]) (i % 2 == 0) ? a : b ];
echo(result); //ECHO: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

索引向量中的元素

[編輯 | 編輯原始碼]

向量中的元素從 0 到 n-1 編號,其中 n 是 len() 返回的長度。使用以下符號訪問向量中的元素

e[5]           // element no 5 (sixth) at   1st nesting level
e[5][2]        // element 2 of element 5    2nd nesting level
e[5][2][0]     // element 0 of 2 of 5       3rd nesting level
e[5][2][0][1]  // element 1 of 0 of 2 of 5  4th nesting level
長度從 len() 開始的示例元素
e = [ [1], [], [3,4,5], "string", "x", [[10,11],[12,13,14],[[15,16],[17]]] ];  // length 6

address       length  element
e[0]          1       [1]
e[1]          0       []
e[5]          3       [ [10,11], [12,13,14], [[15,16],[17]] ]
e[5][1]       3       [ 12, 13, 14 ]
e[5][2]       2       [ [15,16], [17] ]
e[5][2][0]    2       [ 15, 16 ]
e[5][2][0][1] undef   16
    
e[3]          6       "string"
e[3 ][2]      1       "r"
  
s = [2,0,5]; a = 2;
s[a]          undef   5
e[s[a]]       3       [ [10,11], [12,13,14], [[15,16],[17]] ]

字串索引

[編輯 | 編輯原始碼]

可以訪問字串的元素(字元)

"string"[2]    //resolves to "r"

點符號索引

[編輯 | 編輯原始碼]

可以使用另一種點符號訪問向量的前三個元素

e.x    //equivalent to e[0]
e.y    //equivalent to e[1]
e.z    //equivalent to e[2]

向量運算子

[編輯 | 編輯原始碼]

[注意: 需要版本 2015.03]

concat() 將 2 個或多個向量的元素組合成一個向量。巢狀級別不會發生變化。

 vector1 = [1,2,3]; vector2 = [4]; vector3 = [5,6];
 new_vector = concat(vector1, vector2, vector3); // [1,2,3,4,5,6]
  
 string_vector = concat("abc","def");                 // ["abc", "def"]
 one_string = str(string_vector[0],string_vector[1]); // "abcdef"

len() 是一個函式,它返回向量或字串的長度。元素的索引從 [0] 到 [length-1]。

向量
返回此級別的元素數量。
不是向量的單個值會引發錯誤。
字串
返回字串中的字元數量。
 a = [1,2,3]; echo(len(a));   //  3

請參閱長度為的示例元素

矩陣是一個向量向量。

Example that defines a 2D rotation matrix
mr = [
     [cos(angle), -sin(angle)],
     [sin(angle),  cos(angle)]
    ];

獲取輸入

[編輯 | 編輯原始碼]

沒有從鍵盤獲取變數輸入或從任意檔案讀取的機制。沒有提示機制、輸入視窗或輸入欄位,也沒有任何方法可以在指令碼執行時手動輸入資料。

資料只能在指令碼開始時作為常量設定,以及透過訪問少數檔案格式(如 stl、dxf、png 等)中的資料。

除了 DXF 檔案之外,指令碼無法訪問這些資料,儘管在有限程度上,指令碼可能能夠將資料作為一個整體進行操作。例如,STL 檔案可以在 OpenSCAD 中渲染、平移、剪下等。但構成 STL 檔案的內部資料是不可訪問的。

現在我們有了變數,能夠將輸入獲取到變數中而不是從程式碼中設定值會很好。有一些函式可以從 DXF 檔案中讀取資料,或者你可以在命令列上使用 -D 開關設定一個變數。

從繪圖中獲取一個點

[編輯 | 編輯原始碼]

獲取一個點對於在技術圖紙中讀取二維檢視中的原點很有用。函式 dxf_cross 讀取你在指定圖層上兩條線的交點,並返回交點。這意味著該點必須在 DXF 檔案中用兩條線給出,而不是用一個點實體給出。

OriginPoint = dxf_cross(file="drawing.dxf", layer="SCAD.Origin", 
                        origin=[0, 0], scale=1);

獲取一個尺寸值

[編輯 | 編輯原始碼]

你可以從技術圖紙中讀取尺寸。這可以用於讀取旋轉角度、擠出高度或零件之間的間距。在圖紙中,建立一個不顯示尺寸值而是顯示識別符號的尺寸。要讀取該值,你需要在程式中指定這個識別符號

TotalWidth = dxf_dim(file="drawing.dxf", name="TotalWidth",
                        layer="SCAD.Origin", origin=[0, 0], scale=1);

有關這兩個函式的良好示例,請參閱示例 009 和OpenSCAD 主頁上的影像

第 2 章 - 3D 物件

[編輯 | 編輯原始碼]

OpenSCAD 使用者手冊/OpenSCAD 語言

立方體

[編輯 | 編輯原始碼]

在第一個卦限中建立立方體或長方體(即“盒子”)。 當center為true時,立方體以原點為中心。 如果按此處顯示的順序給出,引數名稱是可選的。

cube(size = [x,y,z], center = true/false);
cube(size =  x ,     center = true/false);
引數:
大小
單個值,所有邊都為該長度的立方體
3個值的陣列[x,y,z],尺寸分別為x、y和z的長方體。
中心
false(預設值),第一個(正)卦限,一個角在(0,0,0)處
true,立方體以(0,0,0)為中心
default values:  cube();   yields:  cube(size = [1, 1, 1], center = false);
示例:

equivalent scripts for this example
 cube(size = 18);
 cube(18);
 cube([18,18,18]);
 .
 cube(18,false);
 cube([18,18,18],false);
 cube([18,18,18],center=false);
 cube(size = [18,18,18], center = false);
 cube(center = false,size = [18,18,18] );

equivalent scripts for this example
 cube([18,28,8],true);
 box=[18,28,8];cube(box,true);

在座標系的原點建立一個球體。 r引數名稱是可選的。 要使用d而不是r,則必須命名d。

引數

r
半徑。 這是球體的半徑。 球體的解析度基於球體的大小以及$fa、$fs和$fn變數。 有關這些特殊變數的更多資訊,請參閱:OpenSCAD_User_Manual/其他語言功能
d
直徑。 這是球體的直徑。
$fa
片段角度(以度為單位)
$fs
片段大小(以毫米為單位)
$fn
解析度
 default values:  sphere();   yields:   sphere($fn = 0, $fa = 12, $fs = 2, r = 1);

使用示例

sphere(r = 1);
sphere(r = 5);
sphere(r = 10);
sphere(d = 2);
sphere(d = 10);
sphere(d = 20);
// this creates a high resolution sphere with a 2mm radius
sphere(2, $fn=100); 
// also creates a 2mm high resolution sphere but this one 
// does not have as many small triangles on the poles of the sphere
sphere(2, $fa=5, $fs=0.1); 

Sample OpenSCAD spheres, showing clearly the difference in scale.

圓柱體

[編輯 | 編輯原始碼]

圍繞z軸建立一個圓柱體或圓錐體。 當center為true時,它也沿著z軸垂直居中。

如果按此處顯示的順序給出,引數名稱是可選的。 如果命名了一個引數,則所有後續引數也必須命名。

cylinder(h = height, r1 = BottomRadius, r2 = TopRadius, center = true/false);

說明

第二個和第三個位置引數是r1和r2,如果使用r、d、d1或d2,則必須命名它們。

使用r1和r2或d1和d2,其中任一值為零將形成圓錐形,非零非相等的值將生成圓錐的一部分(圓錐臺)。 r1和d1定義底部的寬度,位於[0,0,0]處,r2和d2定義頂部的寬度。

引數
h : 圓柱體或圓錐體的高度
r  : 圓柱體的半徑。 r1 = r2 = r。
r1 : 半徑,圓錐體的底部。
r2 : 半徑,圓錐體的頂部。
d  : 圓柱體的直徑。 r1 = r2 = d / 2. [注意: 需要版本 2014.03]
d1 : 直徑,圓錐體的底部。 r1 = d1 / 2. [注意: 需要版本 2014.03]
d2 : 直徑,圓錐體的頂部。 r2 = d2 / 2. [注意: 需要版本 2014.03]
中心
false(預設值),z的範圍從0到h
true,z的範圍從-h/2到+h/2
$fa : 每個片段的最小角度(以度為單位)。
$fs : 每個片段的最小周長長度。
$fn : 固定360度內的片段數量。 大於或等於3的值將覆蓋$fa和$fs
$fa、$fs和$fn必須是命名引數。 單擊此處瞭解更多詳細資訊,
defaults: cylinder();  yields: cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 1, r2 = 1, center = false);

equivalent scripts
 cylinder(h=15, r1=9.5, r2=19.5, center=false);
 cylinder(  15,    9.5,    19.5, false);
 cylinder(  15,    9.5,    19.5);
 cylinder(  15,    9.5, d2=39  );
 cylinder(  15, d1=19,  d2=39  );
 cylinder(  15, d1=19,  r2=19.5);

equivalent scripts
 cylinder(h=15, r1=10, r2=0, center=true);
 cylinder(  15,    10,    0,        true);
 cylinder(h=15, d1=20, d2=0, center=true);
equivalent scripts
 cylinder(h=20, r=10, center=true);
 cylinder(  20,   10, 10,true);
 cylinder(  20, d=20, center=true);
 cylinder(  20,r1=10, d2=20, center=true);
 cylinder(  20,r1=10, d2=2*10, center=true);
使用$fn

較大的$fn值會在更長的渲染時間內建立更平滑、更圓的表面。 有些人在開發過程中使用中等值以實現更快的渲染速度,然後在最終的F6渲染中更改為更大的值。

但是,使用較小的值可能會產生一些有趣的非圓形物體。 這裡展示了一些示例

scripts for these examples
 cylinder(20,20,20,$fn=3);
 cylinder(20,20,00,$fn=4);
 cylinder(20,20,10,$fn=4);
尺寸過小的孔

使用圓柱體() 與差() 在物體中放置孔會建立尺寸過小的孔。 這是因為圓形路徑用內接在圓內的多邊形近似。 多邊形的點位於圓上,但點之間的直線在圓內。 要使所有孔都比真正的圓更大,多邊形必須完全位於圓之外(外接)。 用於外接孔的模組

script for this example
 poly_n = 6;
 color("blue") translate([0, 0, 0.02]) linear_extrude(0.1) circle(10, $fn=poly_n);
 color("green") translate([0, 0, 0.01]) linear_extrude(0.1) circle(10, $fn=360);
 color("purple") linear_extrude(0.1) circle(10/cos(180/poly_n), $fn=poly_n);

一般來說,半徑為 的多邊形的任一邊中點的半徑為 。 如果只知道中點半徑 (例如,要將六角扳手放入六角形孔中),則多邊形半徑為

多面體

[編輯 | 編輯原始碼]

多面體是最通用的 3D 基本實體。 它可以用來建立任何規則或不規則形狀,包括那些具有凹面和凸面特徵的形狀。 曲面由一系列平面近似。

polyhedron( points = [ [X0, Y0, Z0], [X1, Y1, Z1], ... ], triangles = [ [P0, P1, P2], ... ], convexity = N);   // before 2014.03
polyhedron( points = [ [X0, Y0, Z0], [X1, Y1, Z1], ... ], faces = [ [P0, P1, P2, P3, ...], ... ], convexity = N);   // 2014.03 & later
引數
3d 點或頂點的向量。 每個點又是一個向量 [x,y,z],表示它的座標。
點可以按任何順序定義。 N 個點按定義的順序被引用為 0 到 N-1。
三角形 [已棄用: 三角形將在將來的版本中刪除。 請改用 引數]
面的向量,它們共同包圍了實體。 每個面都是一個向量,包含來自點向量中的 3 個點的索引(從 0 開始)。
[注意: 需要版本 2014.03]
面的向量,它們共同包圍了實體。 每個面都是一個向量,包含來自點向量中的 3 個或更多點的索引(從 0 開始)。
面可以按任何順序定義,但每個面的點必須按正確的順序排列(見下文)。 定義足夠的面來完全包圍實體,並且沒有重疊。
如果描述單個面的點不在同一個平面上,則面將根據需要自動拆分為三角形。
凸性
整數。 凸性引數指定與物體相交的射線可能穿透的最大面數。 此引數僅用於在 OpenCSG 預覽模式中正確顯示物體。 它對多面體渲染沒有影響。 對於顯示問題,將它設定為 10 在大多數情況下應該可以正常工作。
 default values: polyhedron(); yields: polyhedron(points = undef, faces = undef, convexity = 1);


在面的列表中,對於每個面,您可以從哪個點開始是任意的,但是面的點(由點列表中的索引引用)必須在從外部向內檢視每個面時按順時針方向排列。 後面從後面檢視,底部從底部檢視,等等。 記住此排序要求的另一種方法是使用右手定則。 使用你的右手,將你的拇指向上伸出,並像豎起大拇指一樣捲起你的手指,將你的拇指指向面,並按你手指捲起的方向排列點。 在下面的示例中嘗試一下。


示例 1 使用多面體生成 cube( [ 10, 7, 5 ] );
立方體的點號
展開的立方體面

CubePoints = [ [ 0, 0, 0 ], //0 [ 10, 0, 0 ], //1 [ 10, 7, 0 ], //2 [ 0, 7, 0 ], //3 [ 0, 0, 5 ], //4 [ 10, 0, 5 ], //5 [ 10, 7, 5 ], //6 [ 0, 7, 5 ]]; //7 CubeFaces = [ [0,1,2,3], // bottom [4,5,1,0], // front [7,6,5,4], // top [5,6,2,1], // right [6,7,3,2], // back [7,4,0,3]]; // left polyhedron( CubePoints, CubeFaces );
equivalent descriptions of the bottom face
  [0,1,2,3],
  [0,1,2,3,0],
  [1,2,3,0],
  [2,3,0,1],
  [3,0,1,2],
  [0,1,2],[2,3,0],   // 2 triangles with no overlap
  [1,2,3],[3,0,1],
  [1,2,3],[0,1,3],
示例 2 一個正方形底座的金字塔
一個簡單的多面體,正方形底座的金字塔
polyhedron(
  points=[ [10,10,0],[10,-10,0],[-10,-10,0],[-10,10,0], // the four points at base
           [0,0,10]  ],                                 // the apex point 
  faces=[ [0,1,4],[1,2,4],[2,3,4],[3,0,4],              // each triangle side
              [1,0,3],[2,1,3] ]                         // two triangles for square base
 );
示例 3 一個三角稜柱

注意:本示例中存在錯誤,一位目光銳利的 CAD 工程師注意到展開的三角形不正確,斜邊應為 1,5 & 0,4。正確的展開方式是將它們與矩形 A 相鄰,沿著 1,2 & 0,3 邊。程式碼已修正,希望修正後的影像會盡快出現。

多面體三角稜柱
  module prism(l, w, h){
      polyhedron(//pt 0        1        2        3        4        5
              points=[[0,0,0], [l,0,0], [l,w,0], [0,w,0], [0,w,h], [l,w,h]],
              faces=[[0,1,2,3],[5,4,3,2],[0,4,5,1],[0,3,4],[5,2,1]]
              );
      
      // preview unfolded (do not include in your function
      z = 0.08;
      separation = 2;
      border = .2;
      translate([0,w+separation,0])
          cube([l,w,z]);
      translate([0,w+separation+w+border,0])
          cube([l,h,z]);
      translate([0,w+separation+w+border+h+border,0])
          cube([l,sqrt(w*w+h*h),z]);
      translate([l+border,w+separation,0])
          polyhedron(//pt 0       1       2        3       4       5
                  points=[[0,0,0],[h,w,0],[0,w,0], [0,0,z],[h,w,z],[0,w,z]],
                  faces=[[0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0]]
                  );
      translate([0-border,w+separation,0])
          polyhedron(//pt 0       1         2        3       4         5
                  points=[[0,0,0],[0-h,w,0],[0,w,0], [0,0,z],[0-h,w,z],[0,w,z]],
                  faces=[[1,0,2],[5,3,4],[0,1,4,3],[1,2,5,4],[2,0,3,5]]
                  );
      }
  
  prism(10, 5, 3);

除錯多面體

[編輯 | 編輯原始碼]

定義多面體時常見的錯誤包括:所有面沒有按順時針順序排列(從外部觀察 - 底部需要從下面觀察),面重疊,以及缺少面或面的一部分。一般來說,多面體面還應滿足流形條件。

  • 任何多面體邊上應恰好有兩個面相交。
  • 如果兩個面共用一個頂點,它們應該在圍繞該頂點的同一循環面-邊中。

第一條規則消除了像兩個共用一條邊的立方體,以及不具有水密性的模型這樣的多面體;第二條規則消除了像兩個共用一個頂點的立方體這樣的多面體。

從外部觀察時,描述每個面的點必須按相同的順時針順序排列,並提供了一種檢測逆時針順序的機制。當使用 F12 與 F5 結合的“隨機排列”檢視時,逆時針面將以粉色顯示。重新排列不正確面的點。旋轉物體以檢視所有面。可以使用 F10 關閉粉色檢視。

OpenSCAD 允許臨時註釋掉部分面描述,以便只顯示剩餘的面。使用 // 註釋掉其餘部分。使用 /* 和 */ 開始和結束註釋塊。這可以是行的一部分,也可以擴充套件到多行。僅檢視部分面有助於確定單個面的正確點。注意,不會顯示實體,只會顯示面。如果使用 F12,所有面都會有一側是粉色的。註釋掉一些面也有助於顯示任何內部面。


示例 1 只顯示 2 個面
CubeFaces = [
/* [0,1,2,3],  // bottom
   [4,5,1,0],  // front */
   [7,6,5,4],  // top
/* [5,6,2,1],  // right
   [6,7,3,2],  // back */
   [7,4,0,3]]; // left


定義多面體後,其預覽可能看起來是正確的。多面體本身甚至可能渲染得很好。但是,為了確保它是一個有效的流形,並且可以生成一個有效的 STL 檔案,請將其與任何立方體合併並渲染它(F6)。如果多面體消失了,則意味著它不正確。修改所有面的繞組順序,以及上面提到的兩條規則。

面順序錯誤

[編輯 | 編輯原始碼]

示例 4 具有面順序錯誤的更復雜的多面體

從檢視選單中選擇“隨機排列”,然後編譯(預覽 F5)設計(不是編譯和渲染!),預覽將顯示突出顯示的面向錯誤的多邊形。不幸的是,這種突出顯示在 OpenCSG 預覽模式中不可用,因為它會干擾 OpenCSG 預覽模式的實現方式。)

下面您可以看到程式碼和這樣一個有問題的多面體的圖片,錯誤的多邊形(面或面的組合)以粉色顯示。

// Bad polyhedron
polyhedron
    (points = [
	       [0, -10, 60], [0, 10, 60], [0, 10, 0], [0, -10, 0], [60, -10, 60], [60, 10, 60], 
	       [10, -10, 50], [10, 10, 50], [10, 10, 30], [10, -10, 30], [30, -10, 50], [30, 10, 50]
	       ], 
     faces = [
		  [0,2,3],   [0,1,2],  [0,4,5],  [0,5,1],   [5,4,2],  [2,4,3],
                  [6,8,9],  [6,7,8],  [6,10,11], [6,11,7], [10,8,11],
		  [10,9,8], [0,3,9],  [9,0,6], [10,6, 0],  [0,4,10],
                  [3,9,10], [3,10,4], [1,7,11],  [1,11,5], [1,7,8],  
                  [1,8,2],  [2,8,11], [2,11,5]
		  ]
     );
具有面向錯誤的多邊形的多面體

正確的多面體如下所示

polyhedron
    (points = [
	       [0, -10, 60], [0, 10, 60], [0, 10, 0], [0, -10, 0], [60, -10, 60], [60, 10, 60], 
	       [10, -10, 50], [10, 10, 50], [10, 10, 30], [10, -10, 30], [30, -10, 50], [30, 10, 50]
	       ], 
     faces = [
		  [0,3,2],  [0,2,1],  [4,0,5],  [5,0,1],  [5,2,4],  [4,2,3],
                  [6,8,9],  [6,7,8],  [6,10,11],[6,11,7], [10,8,11],
		  [10,9,8], [3,0,9],  [9,0,6],  [10,6, 0],[0,4,10],
                  [3,9,10], [3,10,4], [1,7,11], [1,11,5], [1,8,7],  
                  [2,8,1],  [8,2,11], [5,11,2]
		  ]
     );
初學者小貼士

如果您不理解“方向”,請嘗試識別面向錯誤的粉色面,然後反轉對點向量的引用序列,直到得到正確的結果。例如,在上面的例子中,第三個三角形([0,4,5])是錯誤的,我們將其修正為 [4,0,5]。請記住,面列表是一個迴圈列表。此外,您可以從“檢視選單”中選擇“顯示邊”,列印螢幕截圖,並對點和麵進行編號。在我們的示例中,點用黑色標註,面用藍色標註。如果需要,將物體翻轉過來,並從背面製作第二個副本。這樣您就可以跟蹤。

順時針技術

方向由順時針迴圈索引確定。這意味著,如果您從外部觀察三角形(在本例中為 [4,0,5]),您會看到路徑圍繞面的中心是順時針方向。繞組順序 [4,0,5] 是順時針方向,因此是正確的。繞組順序 [0,4,5] 是逆時針方向,因此是錯誤的。同樣,[4,0,5] 的任何其他順時針順序都有效:[5,4,0] & [0,5,4] 也是正確的。如果您使用順時針技術,您的面將始終位於外部(OpenSCAD 的外部,其他程式將逆時針方向用作外部)。

將其視為“左手規則”

如果您將左手放在面上,手指彎曲的方向與點的順序一致,您的拇指應該指向外側。如果您的拇指指向內側,您需要反轉繞組順序。

具有面向錯誤的多邊形的多面體

“多面體”的簡潔描述

  • 點定義了形狀中的所有點/頂點。
  • 面是連線點/頂點的多邊形列表。

點列表中的每個點都用一個 3 元組 x,y,z 位置規範定義。點列表中的點自動從零開始編號,以便在面列表中使用(0,1,2,3,... 等)。

面列表中的每個面都透過從點列表中選擇 3 個或更多個點(使用點順序號)來定義。

例如,faces=[ [0,1,2] ] 定義了一個從第一個點(點從零開始編號)到第二個點,然後到第三點的三角形。

從外部觀察任何面時,面必須按順時針順序列出所有點。

多面體點列表中的點重複

[編輯 | 編輯原始碼]

多面體定義的點列表可能包含重複項。當兩個或多個點具有相同的座標時,它們被視為相同的多面體頂點。因此,以下多面體

points = [[ 0, 0, 0], [10, 0, 0], [ 0,10, 0],
          [ 0, 0, 0], [10, 0, 0], [ 0,10, 0],
          [ 0,10, 0], [10, 0, 0], [ 0, 0,10],
          [ 0, 0, 0], [ 0, 0,10], [10, 0, 0],
          [ 0, 0, 0], [ 0,10, 0], [ 0, 0,10]];
polyhedron(points, [[0,1,2], [3,4,5], [6,7,8], [9,10,11], [12,13,14]]);

定義與以下多面體相同的四面體

points = [[0,0,0], [0,10,0], [10,0,0], [0,0,10]];
polyhedron(points, [[0,2,1], [0,1,3], [1,2,3], [0,3,2]]);

3D 到 2D 投影

[編輯 | 編輯原始碼]

使用 projection() 函式,您可以從 3D 模型建立 2D 圖紙,並將其匯出為 dxf 格式。它的工作原理是將 3D 模型投影到 (x,y) 平面,z 為 0。如果 cut=true,則只考慮 z=0 的點(有效地切割物體),如果 cut=false預設值),則也考慮平面以上和以下的點(建立適當的投影)。

示例:考慮 OpenSCAD 附帶的 example002.scad。

然後您可以執行“切割”投影,這將為您提供 z=0 時 x-y 平面的“切片”。

projection(cut = true) example002();

您還可以執行“普通”投影,這將為您提供物體在 xy 平面上的“陰影”。

projection(cut = false) example002();

另一個示例

您還可以使用投影獲取物體的“側檢視”。讓我們以 example002 為例,將其向上移動到 X-Y 平面之外,並旋轉它

translate([0,0,25]) rotate([90,0,0]) example002();

現在我們可以使用 projection() 獲取側檢視

projection() translate([0,0,25]) rotate([90,0,0]) example002();

連結

第 3 章 - 2D 物件

[編輯 | 編輯原始碼]

OpenSCAD 使用者手冊/OpenSCAD 語言

所有 2D 圖元都可以用 3D 變換進行變換。它們通常用作 3D 擠出的部分。雖然它們無限薄,但它們以 1 個單位的厚度渲染。

注意:嘗試使用 difference() 從 3D 物體中減去會導致最終渲染結果出乎意料。

正方形

[編輯 | 編輯原始碼]

在第一象限中建立一個正方形或矩形。當 center 為真時,正方形將以原點為中心。如果按此處顯示的順序給出,則引數名稱是可選的。

square(size = [x, y], center = true/false);
square(size =  x    , center = true/false);
引數:
大小
單個值,兩邊都為該長度的正方形
2 值陣列 [x,y],尺寸為 x 和 y 的矩形
中心
false(預設),第一(正)象限,一個角在 (0,0)
true,正方形以 (0,0) 為中心
default values:  square();   yields:  square(size = [1, 1], center = false);
示例:

10x10 square

equivalent scripts for this example
 square(size = 10);
 square(10);
 square([10,10]);
 .
 square(10,false);
 square([10,10],false);
 square([10,10],center=false);
 square(size = [10, 10], center = false);
 square(center = false,size = [10, 10] );

OpenScad square 20x10

equivalent scripts for this example
 square([20,10],true);
 a=[20,10];square(a,true);

在原點建立一個圓形。除 r 外,所有引數必須命名。

circle(r=radius | d=diameter);
引數
r : 圓形半徑。r 名是圓形中唯一可選的名稱。
圓形解析度基於大小,使用 $fa 或 $fs。
對於一個小而高解析度的圓形,您可以建立一個大圓形,然後將其縮小,或者您可以設定 $fn 或其他特殊變數。注意:這些示例超出了 3D 印表機以及顯示屏的解析度。
scale([1/100, 1/100, 1/100]) circle(200); // create a high resolution circle with a radius of 2.
circle(2, $fn=50);                        // Another way.
d  : 圓形直徑(僅在 2014.03 之後版本可用)。
$fa : 每個片段的最小角度(以度為單位)。
$fs : 每個片段的最小周長長度。
$fn : 360 度中固定的分段數。大於或等於 3 的值會覆蓋 $fa 和 $fs。
如果使用它們,$fa、$fs 和 $fn 必須是命名引數。單擊此處瞭解詳細資訊
defaults:  circle(); yields:  circle($fn = 0, $fa = 12, $fs = 2, r = 1);

circle for user manual description

此示例的等效指令碼

 circle(10);
 circle(r=10);
 circle(d=20);
 circle(d=2+9*2);

可以透過使用 scale()resize() 使 x 和 y 維度不等來從圓形建立橢圓。請參閱OpenSCAD 使用者手冊/變換

Ellipse from circle Ellipse from circle top view

equivalent scripts for this example
 resize([30,10])circle(d=20);
 scale([1.5,.5])circle(d=20);

正多邊形

[編輯 | 編輯原始碼]

可以透過使用 circle() 將 $fn 設定為邊數來建立 3 個或更多個邊的正多邊形。以下兩段程式碼等效。

 circle(r=1, $fn=4);
 module regular_polygon(order = 4, r=1){
     angles=[ for (i = [0:order-1]) i*(360/order) ];
     coords=[ for (th=angles) [r*cos(th), r*sin(th)] ];
     polygon(coords);
 }
 regular_polygon();

它們將產生以下形狀,其中多邊形內接於圓形,所有邊(和角)相等。一個角指向正 x 方向。對於不規則形狀,請參閱下面的多邊形圖元。

script for these examples
 translate([-42,  0]){circle(20,$fn=3);%circle(20,$fn=90);}
 translate([  0,  0]) circle(20,$fn=4);
 translate([ 42,  0]) circle(20,$fn=5);
 translate([-42,-42]) circle(20,$fn=6);
 translate([  0,-42]) circle(20,$fn=8);
 translate([ 42,-42]) circle(20,$fn=12);
 
 color("black"){
     translate([-42,  0,1])text("3",7,,center);
     translate([  0,  0,1])text("4",7,,center);
     translate([ 42,  0,1])text("5",7,,center);
     translate([-42,-42,1])text("6",7,,center);
     translate([  0,-42,1])text("8",7,,center);
     translate([ 42,-42,1])text("12",7,,center);
 }

多邊形

[編輯 | 編輯原始碼]

函式 polygon() 使用 x,y 座標列表建立一個多邊形形狀。多邊形是最強大的 2D 物件,它可以建立圓形和正方形可以建立的任何東西,以及更多。這包括具有凹邊和凸邊的不規則形狀。此外,它可以在該形狀內放置孔。

polygon(points = [ [x, y], ... ], paths = [ [p1, p2, p3..], ...], convexity = N);
引數
多邊形的 x,y 點列表:2 個元素向量的向量。
注意:點從 0 到 n-1 索引。
路徑
預設
如果沒有指定路徑,所有點將按列表中的順序使用。
單個向量
遍歷點的順序。使用從 0 到 n-1 的索引。可以按不同的順序使用,可以使用列表中所有點或部分點。
多個向量
建立主形狀和次要形狀。次要形狀從主形狀中減去(類似於 difference())。次要形狀可以完全或部分位於主形狀內。
透過從指定的最後一個點返回到第一個點來建立一個封閉形狀。
凸性
"向內" 曲線的整數數量,即透過多邊形的任意線的預期路徑交叉點。見下文。
defaults:   polygon();  yields:  polygon(points = undef, paths = undef, convexity = 1);

沒有孔

[編輯 | 編輯原始碼]

equivalent scripts for this example
 polygon(points=[[0,0],[100,0],[130,50],[30,50]]);
 polygon([[0,0],[100,0],[130,50],[30,50]], paths=[[0,1,2,3]]);
 polygon([[0,0],[100,0],[130,50],[30,50]],[[3,2,1,0]]);
 polygon([[0,0],[100,0],[130,50],[30,50]],[[1,0,3,2]]);
    
 a=[[0,0],[100,0],[130,50],[30,50]];
 b=[[3,0,1,2]];
 polygon(a);
 polygon(a,b);
 polygon(a,[[2,3,0,1,2]]);

一個孔

[編輯 | 編輯原始碼]

equivalent scripts for this example
 polygon(points=[[0,0],[100,0],[0,100],[10,10],[80,10],[10,80]], paths=[[0,1,2],[3,4,5]],convexity=10);

 triangle_points =[[0,0],[100,0],[0,100],[10,10],[80,10],[10,80]];
 triangle_paths =[[0,1,2],[3,4,5]];
 polygon(triangle_points,triangle_paths,10);

第一個路徑向量 [0,1,2] 選擇點 [0,0],[100,0],[0,100] 用於主形狀。第二個路徑向量 [3,4,5] 選擇點 [10,10],[80,10],[10,80] 用於次要形狀。次要形狀從主形狀中減去(考慮 difference())。由於次要形狀完全位於主形狀內,因此它會留下一個帶有孔的形狀。

[注意: 需要版本 2015.03] (用於使用 concat())


      //example polygon with multiple holes
a0 = [[0,0],[100,0],[130,50],[30,50]];     // main
b0 = [1,0,3,2];
a1 = [[20,20],[40,20],[30,30]];            // hole 1
b1 = [4,5,6];
a2 = [[50,20],[60,20],[40,30]];            // hole 2
b2 = [7,8,9];
a3 = [[65,10],[80,10],[80,40],[65,40]];    // hole 3
b3 = [10,11,12,13];
a4 = [[98,10],[115,40],[85,40],[85,10]];   // hole 4
b4 = [14,15,16,17];
a  = concat (a0,a1,a2,a3,a4);
b  = [b0,b1,b2,b3,b4];
polygon(a,b);
      //alternate 
polygon(a,[b0,b1,b2,b3,b4]);

從多邊形擠出 3D 形狀

[編輯 | 編輯原始碼]

   translate([0,-20,10]) {
       rotate([90,180,90]) {
           linear_extrude(50) {
               polygon(
                   points = [
                      //x,y
                       /*
                                  O  .
                       */
                       [-2.8,0],
                       /*
                                O__X  .
                       */
                       [-7.8,0],
                       /*
                              O
                               \
                                X__X  .
                       */
                       [-15.3633,10.30],
                       /*
                              X_______._____O
                               \         
                                X__X  .
                       */
                       [15.3633,10.30],
                       /*
                              X_______._______X
                               \             /
                                X__X  .     O
                       */
                       [7.8,0],
                       /*
                              X_______._______X
                               \             /
                                X__X  .  O__X
                       */
                       [2.8,0],
                       /*
                           X__________.__________X
                            \                   /
                             \              O  /
                              \            /  /
                               \          /  /
                                X__X  .  X__X
                       */
                       [5.48858,5.3],
                       /*
                           X__________.__________X
                            \                   /
                             \   O__________X  /
                              \            /  /
                               \          /  /
                                X__X  .  X__X
                       */
                       [-5.48858,5.3],
                                   ]
                               );
                           }
       }
   }

凸度引數指定與物件相交的光線可能穿透的最大正面數量(背面數量)。此引數僅在 OpenCSG 預覽模式下正確顯示物件時需要,對多面體渲染沒有影響。

此影像顯示一個凸度為 2 的 2D 形狀,因為以紅色指示的光線以最大 2 次穿透 2D 形狀的外部⇒內部(或內部⇒外部)。3D 形狀的凸度將以類似的方式確定。將其設定為 10 對於大多數情況應該可以正常工作。

import_dxf

[編輯 | 編輯原始碼]

[已棄用: import_dxf() 將在將來的版本中刪除。請改用 import()]

讀取 DXF 檔案並建立一個 2D 形狀。

示例

linear_extrude(height = 5, center = true, convexity = 10)
		import_dxf(file = "example009.dxf", layer = "plate");

text 模組使用本地系統上安裝的字型或作為單獨的字型檔案提供的字型,將文字建立為 2D 幾何物件。

[注意: 需要版本 2015.03]

引數

文字
字串。要生成的文字。
大小
十進位制。生成的文字的升高(基線以上的高度)約為給定值。預設值為 10。不同的字型可能略有不同,並且可能不會完全填充指定的大小,通常它們會渲染得略小。在公制系統中,大小為 25.4(1 英寸)將對應於 100pt ⇒ 12pt 字號將是 12×0.254 用於公制轉換或 0.12 英寸。
字型
字串。要使用的字型的名稱。這不是字型檔案的名稱,而是邏輯字型名稱(由 fontconfig 庫內部處理)。這也可以包括樣式引數,見下文。可以使用字型列表對話方塊(幫助 -> 字型列表)獲取已安裝字型和樣式的列表。
halign
字串。文字的水平對齊方式。可能的值為“left”、“center”和“right”。預設值為“left”。
valign
字串。文字的垂直對齊方式。可能的值為“top”、“center”、“baseline”和“bottom”。預設值為“baseline”。
間距
十進位制。增加/減少字元間距的因子。預設值 1 導致字型正常間距,給出大於 1 的值會導致字母間距更大。
方向
字串。文字流的方向。可能的值為“ltr”(從左到右)、“rtl”(從右到左)、“ttb”(從上到下)和“btt”(從下到上)。預設值為“ltr”。
語言
字串。文字的語言(例如,“en”、“ar”、“ch”。預設值為“en”。
指令碼
字串。文字的指令碼(例如,“latin”、“arabic”、“hani”。預設值為“latin”。
$fn
用於細分 freetype 提供的曲線路徑段

示例

示例 1:結果。
text("OpenSCAD");



筆記

為了允許指定特定的 Unicode 字元,可以在字串中使用以下轉義程式碼指定它們;

  • \x03    - 十六進位制字元值(僅支援從017f的十六進位制值)
  • \u0123  - 使用 4 個十六進位制數字的 Unicode 字元(注意:小寫\u)
  • \U012345- 使用 6 個十六進位制數字的 Unicode 字元(注意:大寫\U)

空字元 (NUL) 對映為空格字元 (SP)。

 assert(version() == [2019, 5, 0]);
 assert(ord(" ") == 32);
 assert(ord("\x00") == 32);
 assert(ord("\u0000") == 32);
 assert(ord("\U000000") == 32);

示例

t="\u20AC10 \u263A"; // 10 euro and a smilie

使用字型和樣式

[編輯 | 編輯原始碼]

字型由其邏輯字型名稱指定;此外,可以新增樣式引數以選擇特定的字型樣式,如“粗體”或“斜體”,例如

font="Liberation Sans:style=Bold Italic"

字型列表對話方塊(位於幫助>字型列表下)顯示每個可用字型的字型名稱和字型樣式。為了參考,對話方塊還顯示字型檔案的路徑。您可以將字型列表中的字型拖放到編輯器視窗中以在 text() 語句中使用。

OpenSCAD 字型列表對話方塊

OpenSCAD 包含字型 Liberation MonoLiberation SansLiberation Serif。因此,由於字型通常因平臺型別而異,使用這些包含的字型很可能在平臺之間可移植。

出於這個原因,建議在常用/休閒文字使用中指定這些字型之一。Liberation Sans 是預設字型,以鼓勵這一點。


除了已安裝的字型(對於 Windows,僅以管理員身份為所有使用者安裝的字型)之外,還可以新增專案特定的字型檔案。支援的字型檔案格式為 TrueType 字型 (*.ttf) 和 OpenType 字型 (*.otf)。這些檔案需要使用 use<> 進行註冊。

 use <ttf/paratype-serif/PTF55F.ttf>

註冊後,字型將列在字型列表對話方塊中,因此如果未知字型的邏輯名稱,可以查詢它,因為它已註冊。

OpenSCAD 使用 fontconfig 來查詢和管理字型,因此可以使用命令列上的 fontconfig 工具以類似於 GUI 對話方塊的格式列出系統配置的字型。

$ fc-list -f "%-60{{%{family[0]}%{:style[0]=}}}%{file}\n" | sort

...
Liberation Mono:style=Bold Italic /usr/share/fonts/truetype/liberation2/LiberationMono-BoldItalic.ttf
Liberation Mono:style=Bold        /usr/share/fonts/truetype/liberation2/LiberationMono-Bold.ttf
Liberation Mono:style=Italic      /usr/share/fonts/truetype/liberation2/LiberationMono-Italic.ttf
Liberation Mono:style=Regular     /usr/share/fonts/truetype/liberation2/LiberationMono-Regular.ttf
...

在 Windows 下,字型儲存在 Windows 登錄檔中。要獲取包含字型檔名的檔案,請使用以下命令

reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /s > List_Fonts_Windows.txt


示例

示例 2:結果。
 square(10);
 
 translate([15, 15]) {
   text("OpenSCAD", font = "Liberation Sans");
 }
 
 translate([15, 0]) {
   text("OpenSCAD", font = "Liberation Sans:style=Bold Italic");
 }


垂直對齊

[編輯 | 編輯原始碼]
頂部
文字與給定 Y 座標處的邊界框的頂部對齊。
中心
文字與給定 Y 座標處的邊界框的中心對齊。
基線
文字與給定 Y 座標處的字型基線對齊。這是預設值。
底部
文字與給定 Y 座標處的邊界框的底部對齊。
OpenSCAD 垂直文字對齊
 text = "Align";
 font = "Liberation Sans";
 
 valign = [
   [  0, "top"],
   [ 40, "center"],
   [ 75, "baseline"],
   [110, "bottom"]
 ];
 
 for (a = valign) {
   translate([10, 120 - a[0], 0]) {
     color("red") cube([135, 1, 0.1]);
     color("blue") cube([1, 20, 0.1]);
     linear_extrude(height = 0.5) {
       text(text = str(text,"_",a[1]), font = font, size = 20, valign = a[1]);
     }
   }
 }


多行文字不支援 text(),但將每行大小 × .72 平移將導致 1 em 的行間距(em = 字型的正文高度或點)。可以新增 20%(× 1.2)。

水平對齊

[編輯 | 編輯原始碼]
文字與給定 X 座標處的邊界框左側對齊。這是預設設定。
中心
文字與給定 X 座標處的邊界框中心對齊。
文字與給定 X 座標處的邊界框右側對齊。
OpenSCAD 水平文字對齊
 text = "Align";
 font = "Liberation Sans";
 
 halign = [
   [10, "left"],
   [50, "center"],
   [90, "right"]
 ];
 
 for (a = halign) {
   translate([140, a[0], 0]) {
     color("red") cube([115, 2,0.1]);
     color("blue") cube([2, 20,0.1]);
     linear_extrude(height = 0.5) {
       text(text = str(text,"_",a[1]), font = font, size = 20, halign = a[1]);
     }
   }
 }


3D 文字

[編輯 | 編輯原始碼]

可以使用 linear_extrude 函式將文字從二維物件更改為三維物件。

//3d Text Example
linear_extrude(4)
    text("Text");
3D 文字示例

擠出 是使用固定橫截面輪廓建立物體的過程。OpenSCAD 提供兩個命令來從二維形狀建立三維實體:linear_extrude() 和 rotate_extrude()。線性擠出類似於將橡皮泥透過帶有特定形狀模具的壓機。

linear_extrude() 就像橡皮泥擠出壓機

旋轉擠出類似於 車削 或在 陶輪 上“拋制”碗的過程。

rotate_extrude() 模擬拋制器皿

兩種擠出方法都適用於位於 X-Y 平面的(可能是分離的)二維形狀。雖然在二維形狀和三維實體上進行的變換可以將形狀移出 X-Y 平面,但在執行擠出時,最終結果並不直觀。實際上,任何三維座標資訊(Z 座標)都會被任何二維形狀忽略,這個過程相當於在執行擠出之前對任何二維形狀執行隱式 projection()。建議對嚴格位於 X-Y 平面的形狀執行擠出。

linear_extrude

[編輯 | 編輯原始碼]

線性擠出是一個將二維物件作為輸入並生成三維物件作為結果的操作。

擠出遵循 V 向量,該向量預設為 Z 軸,為了指定自定義值,需要使用大於 2021.01 的版本。

在 OpenSCAD 中,擠出始終對二維物件的 xy 平面的投影(陰影)執行;因此,如果你在擠出之前對二維物件進行旋轉或應用其他變換,其陰影形狀將被擠出。

雖然擠出沿著 V 向量是線性的,但有一個扭曲引數可用,它會導致物體在向上擠出時繞 V 向量旋轉。這可以用來繞其中心旋轉物體,就像螺旋柱一樣,或者在 V 向量周圍產生螺旋擠出,就像豬尾巴一樣。

還包括一個比例引數,以便可以擴充套件或收縮物體在擠出的範圍內,從而使擠出向內或向外擴散。

linear_extrude(height = 5, v = [0, 0, 1], center = true, convexity = 10, twist = -fanrot, slices = 20, scale = 1.0, $fn = 16) {...}

由於向後相容性問題,你必須使用引數名稱。

height 必須為正數。

v 是一個三維向量,必須指向正 Z 方向 [注意: 需要版本 開發快照]

$fn 是可選的,它指定線性擠出的解析度(數字越大,“平滑度”越高,但需要更多計算時間)。

如果對非平凡二維形狀執行擠出失敗,請嘗試設定凸度引數(預設值不是 10,但 10 是一個“好”的值,可以嘗試一下)。見下面的解釋。

扭曲是指形狀擠出的角度數。將引數 twist 設定為 360 會擠出整整一圈。扭曲方向遵循左手定則。

twist = 0

0° 的扭曲

linear_extrude(height = 10, center = true, convexity = 10, twist = 0)
translate([2, 0, 0])
circle(r = 1);

twist = -100

-100° 的扭曲

linear_extrude(height = 10, center = true, convexity = 10, twist = -100)
translate([2, 0, 0])
circle(r = 1);

twist = 100

100° 的扭曲

linear_extrude(height = 10, center = true, convexity = 10, twist = 100)
translate([2, 0, 0])
circle(r = 1);

twist = -500

-500° 的扭曲

linear_extrude(height = 10, center = true, convexity = 10, twist = -500)
translate([2, 0, 0])
circle(r = 1);

它類似於圓柱體的引數 center。如果 center 為 false,則線性擠出 Z 範圍為 0 到 height;如果為 true,則範圍為 -height/2 到 height/2。


center = true

center = true

linear_extrude(height = 10, center = true, convexity = 10, twist = -500)
translate([2, 0, 0])
circle(r = 1);


center = false

center = false

linear_extrude(height = 10, center = false, convexity = 10, twist = -500)
translate([2, 0, 0])
circle(r = 1);

網格細化

[編輯 | 編輯原始碼]

slices 引數定義擠出 Z 軸上的中間點數。其預設值隨扭曲值的增加而增加。顯式設定 slices 可能會提高輸出細化。此外,segments 引數會向擠出多邊形新增頂點(點),從而產生更平滑的扭曲幾何體。segments 需要是多邊形片段的倍數才能產生效果(對於 circle($fn=3),為 6 或 9..;對於 square(),為 8、12..)。

slices = 100

linear_extrude(height = 10, center = false, convexity = 10, twist = 360, slices = 100)
translate([2, 0, 0])
circle(r = 1);

特殊變數 $fn、$fs 和 $fa 也可以用來提高輸出。如果未定義 slices,則其值將從定義的 $fn 值中獲取。

$fn = 100

linear_extrude(height = 10, center = false, convexity = 10, twist = 360, $fn = 100)
translate([2, 0, 0])
circle(r = 1);

在擠出高度上按此值縮放二維形狀。比例可以是標量或向量。

 linear_extrude(height = 10, center = true, convexity = 10, scale=3)
 translate([2, 0, 0])
 circle(r = 1);

OpenScad linear_extrude scale example

 linear_extrude(height = 10, center = true, convexity = 10, scale=[1,5], $fn=100)
 translate([2, 0, 0])
 circle(r = 1);

OpenScad linear_extrude scale example2

注意,如果比例是向量,則生成的側壁可能是非平面的。使用 twist=0slices 引數來避免 不對稱

 linear_extrude(height=10, scale=[1,0.1], slices=20, twist=0)
 polygon(points=[[0,0],[20,10],[20,-10]]);

與匯入的 SVG 一起使用

[編輯 | 編輯原始碼]

此函式的常見用法是匯入二維 svg

 linear_extrude(height = 10, center = true)
 import("knight.svg");

rotate_extrude

[編輯 | 編輯原始碼]

旋轉擠出將二維形狀繞 Z 軸旋轉,形成具有旋轉對稱性的實體。理解此操作的一種方式是想象一個放置在 X-Y 平面上的陶輪,其旋轉軸指向 +Z。然後將要製作的物體放在這個虛擬的陶輪上(可能延伸到 X-Y 平面以下,指向 -Z)。要製作的物體是在 X-Y 平面上的物體的橫截面(只保留右側,X >= 0)。這就是將作為子項提供給 rotate_extrude() 以生成該實體的二維形狀。請注意,物體最初位於 X-Y 平面,但傾斜向上(繞 X 軸旋轉 +90 度)以擠出。

由於二維形狀由 OpenSCAD 在 X-Y 平面上渲染,理解此操作的另一種方式如下:將二維形狀繞 Y 軸旋轉形成實體。生成的實體放置使其旋轉軸位於 Z 軸上。

與 linear_extrude 一樣,擠出始終對二維多邊形到 XY 平面的投影執行。應用於二維多邊形在擠出之前的變換(如 rotate、translate 等)會修改二維多邊形到 XY 平面的投影,因此也會修改最終三維物件的外觀。

  • 二維多邊形在 Z 方向上的平移對結果沒有影響(因為投影也不受影響)。
  • 在 X 方向上的平移會增加最終物體的直徑。
  • 在 Y 方向上的平移會導致最終物體在 Z 方向上發生偏移。
  • 繞 X 軸或 Y 軸的旋轉會扭曲最終物體的橫截面,因為對 XY 平面的投影也會扭曲。

不要混淆,因為 OpenSCAD 在 Z 方向上渲染帶有特定高度的二維多邊形,所以二維物體(及其高度)似乎在 XY 平面上有更大的投影。但對於投影到 XY 平面的情況,以及之後進行擠出操作,只使用沒有高度的基多邊形。

它不能用於生成螺旋線或螺紋。 (這些可以透過使用 twist 引數的 linear_extrude() 來完成。)

二維形狀**必須**完全位於 Y 軸的右側(推薦)或左側。 更準確地說,形狀的**每個**頂點必須滿足 x >= 0 或 x <= 0。如果形狀跨越 X 軸,控制檯視窗會顯示警告,並且 ignore rotate_extrude()。如果二維形狀與 Y 軸相交,即 x = 0,則**必須**為一條與 Y 軸相交的直線,而不是一個點,因為點會導致厚度為零的三維物體,這是無效的,並導致 CGAL 錯誤。對於 2016.xxxx 之前的 OpenSCAD 版本,如果形狀位於負軸上,則生成的面的方向將是內向的,這可能會導致不希望有的效果。

用法

[edit | edit source]
rotate_extrude(angle = 360, convexity = 2) {...}
右手定則

由於向後相容性問題,你必須使用引數名稱。

凸性 : 如果對於非平凡的二維形狀,擠出失敗,請嘗試設定凸性引數(預設值不是 10,但 10 是一個值得嘗試的“好”值)。 參見下面的解釋。
角度 [注意: 需要版本 2019.05] : 預設值為 360。指定從正 X 軸開始的掃描角度。掃描方向遵循右手定則,因此負角度將順時針掃描。
$fa : 每個片段的最小角度(以度為單位)。
$fs : 每個片段的最小周長長度。
$fn : 固定360度內的片段數量。 大於或等於3的值將覆蓋$fa和$fs
$fa、$fs和$fn必須是命名引數。 單擊此處瞭解更多詳細資訊,

示例

[edit | edit source]

可以使用旋轉擠出構造一個簡單的環面。

rotate_extrude(convexity = 10)
translate([2, 0, 0])
circle(r = 1);

網格細化

[edit | edit source]

增加構成二維形狀的碎片數量可以提高網格質量,但渲染時間更長。

rotate_extrude(convexity = 10)
translate([2, 0, 0])
circle(r = 1, $fn = 100);

擠出使用的碎片數量也可以增加。

rotate_extrude(convexity = 10, $fn = 100)
translate([2, 0, 0])
circle(r = 1, $fn = 100);

使用 angle 引數(使用 OpenSCAD 版本 2016.xx),可以建模一個鉤子。

OpenSCAD - 一個鉤子
eps = 0.01;
translate([eps, 60, 0])
   rotate_extrude(angle=270, convexity=10)
       translate([40, 0]) circle(10);
rotate_extrude(angle=90, convexity=10)
   translate([20, 0]) circle(10);
translate([20, eps, 0])
   rotate([90, 0, 0]) cylinder(r=10, h=80+eps);

擠出多邊形

[edit | edit source]

也可以對使用者選擇的點構成的多邊形執行擠出操作。

這是一個簡單的多邊形及其 200 步旋轉擠出。(請注意,它已旋轉 90 度以顯示旋轉外觀;rotate_extrude() 需要它平坦)。

rotate([90,0,0])        polygon( points=[[0,0],[2,1],[1,2],[1,3],[3,4],[0,5]] );
rotate_extrude($fn=200) polygon( points=[[0,0],[2,1],[1,2],[1,3],[3,4],[0,5]] );

有關多邊形的更多資訊,請參見:二維基本圖形:多邊形

擠出引數的描述

[edit | edit source]

所有擠出模式的擠出引數

[edit | edit source]
凸性 整數。凸性引數指定與物體相交的光線可能穿過的正面(或背面)的最大數量。此引數僅在使用標準 Goldfeather 演算法時在 OpenCSG 預覽模式中正確顯示物體時需要,對多面體渲染(網格生成)沒有影響。


基本圖形的凸性是基本圖形在單個位置上的正面(或背面)的最大數量。 例如,球體的凸性為 1,環面的凸性為 2。


此影像顯示了一個凸性為 2 的二維形狀,因為用紅色指示的光線與二維形狀最多相交 4 次(2 個正面和 2 個背面)。 三維形狀的凸性將以類似的方式確定。將其設定為 10 應該適用於大多數情況。 一般來說,僅設定較大的數字會導致預覽渲染速度變慢。

僅用於線性擠出的擠出引數

[edit | edit source]
高度 擠出高度
中心 如果為真,則實體在擠出後居中
扭曲 擠出扭曲角度
縮放 在擠出高度上按此值縮放二維形狀。
切片 類似於特殊變數 $fn,但不會傳遞給子二維形狀。
類似於切片,但在多邊形的段上新增點,而不會改變多邊形的形狀。

第 4 章 - 變換

[edit | edit source]

OpenSCAD 使用者手冊/OpenSCAD 語言


基本概念

[edit | edit source]

變換影響其子節點,顧名思義,它們以各種方式變換子節點,例如移動、旋轉或縮放子節點。變換寫在它們影響的物體之前,例如

translate([10,20,30])
    cube(10);

請注意,變換命令後面沒有分號。可以透過使用 '{' 和 '}' 將子樹括起來,將變換應用於一組子節點,例如

translate([0,0,-5])
{
    cube(10);
    cylinder(r=5,h=10);
}

級聯變換用於對最終子節點應用各種變換。級聯是透過巢狀語句實現的,例如

rotate([45,45,45])
    translate([10,20,30])
        cube(10);
組合變換時,順序很重要

組合變換是一個順序過程,從右到左進行。考慮以下兩個變換

color("red")   translate([0,10,0])  rotate([45,0,0])     cube(5);
color("green") rotate([45,0,0])     translate([0,10,0])  cube(5);

雖然它們包含相同的操作,但第一個繞原點旋轉一個立方體,然後根據 translate 指定的偏移量移動它,最後將其顏色設定為紅色。相反,第二個序列首先移動一個立方體,然後繞原點旋轉它,最後將其顏色設定為綠色。在這種情況下,旋轉會導致立方體沿以原點為中心的弧線移動。此弧線的半徑是從原點的距離,由前面的平移設定。旋轉和平移變換的不同排序會導致立方體最終位於不同的位置。

高階概念

[edit | edit source]

由於 OpenSCAD 使用不同的庫來實現功能,這可能會導致變換的 F5 預覽行為出現一些不一致。傳統的變換(translate、rotate、scale、mirror 和 multimatrix)在預覽中使用 OpenGL 執行,而其他更高階的變換,例如 resize,則執行 CGAL 操作,就像 CSG 操作一樣影響底層物體,而不僅僅是變換它。特別地,這可能會影響修飾符字元的顯示,特別是“#”和“%”,其中高亮可能不會直觀地顯示,例如高亮預調整大小的物體,但高亮後縮放的物體。

縮放

[edit | edit source]

使用指定的向量縮放其子元素。引數名稱是可選的。

Usage Example:
scale(v = [x, y, z]) { ... }
cube(10);
translate([15,0,0]) scale([0.5,1,2]) cube(10);

Image showing result of scale() transformation in OpenSCAD

調整大小

[edit | edit source]

修改子物體的尺寸以匹配給定的 x、y 和 z。

resize() 是一個 CGAL 操作,與其他操作(如 render())一樣,使用完整幾何體,因此即使在預覽中,這也會花費時間處理。


使用示例

// resize the sphere to extend 30 in x, 60 in y, and 10 in the z directions.
resize(newsize=[30,60,10]) sphere(r=10);

OpenSCAD Resize example ellipse

如果 x、y 或 z 為 0,則該維度保持原樣。

// resize the 1x1x1 cube to 2x2x1
resize([2,2,0]) cube();

如果 'auto' 引數設定為 true,則會自動縮放任何 0 維以匹配。 例如。

// resize the 1x2x0.5 cube to 7x14x3.5
resize([7,0,0], auto=true) cube([1,2,0.5]);

'auto' 引數也可以在您只希望自動縮放單個維度,並將其他維度保持原樣時使用。

// resize to 10x8x1. Note that the z dimension is left alone.
resize([10,0,0], auto=[true,true,false]) cube([5,4,1]);

圍繞座標系的軸或任意軸,將子元素旋轉 'a' 度。如果引數按照指定順序給出,則引數名稱是可選的。

//Usage:
rotate(a = deg_a, v = [x, y, z]) { ... }  
// or
rotate(deg_a, [x, y, z]) { ... }
rotate(a = [deg_x, deg_y, deg_z]) { ... }
rotate([deg_x, deg_y, deg_z]) { ... }

'a' 引數 (deg_a) 可以是陣列,如上面後面用法的表達;當 deg_a 是陣列時,'v' 引數會被忽略。當 'a' 指定了 多個軸 時,旋轉會按照以下順序應用:先 x 軸,再 y 軸,最後 z 軸。這意味著以下程式碼

rotate(a=[ax,ay,az]) {...}

等效於

rotate(a=[0,0,az]) rotate(a=[0,ay,0]) rotate(a=[ax,0,0]) {...}

例如,要將物體翻轉過來,可以圍繞 'y' 軸旋轉 180 度。

rotate(a=[0,180,0]) { ... }

這通常簡化為

rotate([0,180,0]) { ... }

可選引數 'v' 是一個向量,它決定物體圍繞哪個任意軸旋轉。

當指定單個軸時,'v' 引數允許指定哪個軸是旋轉的基礎。例如,與上面等效,只圍繞 y 軸旋轉

rotate(a=180, v=[0,1,0]) { ... }

當指定單個軸時,'v' 是一個 向量,定義一個任意軸用於旋轉;這與上面的 多個軸 不同。例如,圍繞由向量 [1,1,0] 定義的軸旋轉物體 45 度,

rotate(a=45, v=[1,1,0]) { ... }

image of result of rotate() transformation in OpenSCAD

單個標量引數 旋轉圍繞 Z 軸旋轉。這在二維環境中很有用,因為 Z 軸是唯一的旋轉軸。例如

rotate(45) square(10);

Result of OpenSCAD rotate(45) as 2D render

旋轉規則幫助
[編輯 | 編輯原始碼]
右手定則


對於

rotate([a, b, c]) { ... };

"a" 是圍繞 X 軸的旋轉,從 +Y 軸,朝向 +Z 軸旋轉。
"b" 是圍繞 Y 軸的旋轉,從 +Z 軸,朝向 +X 軸旋轉。
"c" 是圍繞 Z 軸的旋轉,從 +X 軸,朝向 +Y 軸旋轉。

這些都是 右手定則 的情況。將你的右手拇指指向正軸,你的手指顯示旋轉的方向。


因此,如果 "a" 固定為零,並且 "b" 和 "c" 被適當操縱,那麼這就是 球座標系
因此,要從原點構造一個到某個其他點 (x,y,z) 的圓柱體

x= 10; y = 10; z = 10; // point coordinates of end of cylinder
 
length = norm([x,y,z]);  // radial distance
b = acos(z/length); // inclination angle
c = atan2(y,x);     // azimuthal angle

rotate([0, b, c]) 
    cylinder(h=length, r=0.5);
%cube([x,y,z]); // corner of cube should coincide with end of cylinder

Example of OpenSCAD Rotate() used as a spherical coordinate system.

沿著指定向量平移(移動)子元素。引數名稱是可選的。

Example:
translate(v = [x, y, z]) { ... }
cube(2,center = true); 
translate([5,0,0]) 
   sphere(1,center = true);

image of result of the translate() transformation in OpenSCAD

將子元素轉換為原始元素的映象,就好像它是穿過與原點相交的平面的鏡面影像一樣。mirror() 的引數是與原點相交的鏡面平面法向量,這意味著垂直於平面向外延伸的向量。原始物件的每個座標都會改變,使其在這個平面的另一側與平面上最近的點等距。例如,mirror([1,0,0]),對應於指向 x 軸方向的法向量,會產生一個物體,使得所有正 x 座標都變成負 x 座標,所有負 x 座標都變成正 x 座標。

函式簽名

[編輯 | 編輯原始碼]
mirror(v= [x, y, z] ) { ... }

原始影像在右側。注意,映象不會建立副本。與旋轉和縮放一樣,它會改變物體。

rotate([0,0,10]) cube([3,2,1]);
mirror([1,0,0]) translate([1,0,0]) rotate([0,0,10]) cube([3,2,1]);

image of the result of the mirror() transformation in OpenSCAD

multmatrix

[編輯 | 編輯原始碼]

將所有子元素的幾何圖形與給定的 仿射變換 矩陣相乘,其中矩陣為 4×3 - 一個包含 3 個行向量,每個向量有 4 個元素的向量,或者是一個 4×4 矩陣,其第 4 行始終為 [0,0,0,1]。

用法:multmatrix(m = [...]) { ... }

以下是對矩陣中獨立元素(前三行)可以執行的操作的細分

縮放 X沿 Y 軸對 X 進行剪下沿 Z 軸對 X 進行剪下平移 X
沿 X 軸對 Y 進行剪下縮放 Y沿 Z 軸對 Y 進行剪下平移 Y
沿 X 軸對 Z 進行剪下沿 Y 軸對 Z 進行剪下縮放 Z平移 Z

第 4 行被強制為 [0,0,0,1] 並且可以省略,除非你是在將矩陣傳遞給 multmatrix 之前組合矩陣,因為它不會在 OpenSCAD 中處理。每個矩陣都對給定幾何圖形的點進行操作,就好像每個頂點都是一個包含 4 個元素的向量,包含一個 3D 向量,其第 4 個元素隱含為 1,例如 v=[x, y, z, 1]。m 中隱含的第 4 行的作用是保留向量第 4 個元素中的隱含 1,允許平移工作。因此,multmatrix 操作對每個頂點 v 執行 m*v。m 中未指定的所有元素(第 4 行除外)都被視為零。

此示例在 XY 平面中旋轉 45 度並平移 [10,20,30],即與translate([10,20,30]) rotate([0,0,45])相同。

angle=45;
multmatrix(m = [ [cos(angle), -sin(angle), 0, 10],
                 [sin(angle),  cos(angle), 0, 20],
                 [         0,           0, 1, 30],
                 [         0,           0, 0,  1]
              ]) union() {
   cylinder(r=10.0,h=10,center=false);
   cube(size=[10,10,10],center=false);
}

以下示例演示了透過矩陣乘法組合仿射變換矩陣,在最終版本中產生一個等效於 rotate([0, -35, 0]) translate([40, 0, 0]) Obj(); 的變換。請注意,sin 函式上的符號與上面的示例不同,因為正符號必須按 x 到 y、y 到 z、z 到 x 的順序排列,以便旋轉角度對應於右手座標系中圍繞另一個軸的旋轉。

module Obj() {
   cylinder(r=10.0,h=10,center=false);
   cube(size=[10,10,10],center=false);
}

// This itterates into the future 6 times and demonstrates how multimatrix is moving the object around the center point
for(time = [0 : 15 : 90]){
    y_ang=-time;
    mrot_y = [ [ cos(y_ang), 0,  sin(y_ang), 0],
               [         0,  1,           0, 0],
               [-sin(y_ang), 0,  cos(y_ang), 0],
               [         0,  0,           0, 1]
             ];
    mtrans_x = [ [1, 0, 0, 40],
                 [0, 1, 0,  0],
                 [0, 0, 1,  0],
                 [0, 0, 0,  1]
               ];

    echo(mrot_y*mtrans_x);
    
    // This is the object at [0,0,0]
    Obj();
    
    // This is the starting object at the [40,0,0] coordinate
    multmatrix(mtrans_x) Obj();
    
    // This is the one rotating and appears 6 times
    multmatrix(mrot_y * mtrans_x) Obj();
};

此示例傾斜模型,這是其他變換無法實現的。

M = [ [ 1  , 0  , 0  , 0   ],
      [ 0  , 1  , 0.7, 0   ],  // The "0.7" is the skew value; pushed along the y axis as z changes.
      [ 0  , 0  , 1  , 0   ],
      [ 0  , 0  , 0  , 1   ] ] ;
multmatrix(M) {  union() {
    cylinder(r=10.0,h=10,center=false);
    cube(size=[10,10,10],center=false); 
} }

此示例顯示瞭如何使用 multmatrix 向量變換向量,例如,可以依次變換點陣列(多邊形)中的所有點。向量 (v) 使用旋轉矩陣 (m) 變換,得到一個新的向量 (vtrans),該向量現在被旋轉並且沿著以 z 軸為中心、半徑為 v 的圓形路徑移動,而不會旋轉立方體。

angle=45;
 m=[
        [cos(angle), -sin(angle), 0, 0],
        [sin(angle),  cos(angle), 0, 0],
        [         0,           0, 1, 0]
   ];
              
v=[10,0,0];
vm=concat(v,[1]); // need to add [1]
vtrans=m*vm;
echo(vtrans);
translate(vtrans)cube();

更多?

[編輯 | 編輯原始碼]

在此瞭解更多資訊

使用指定的 RGB 顏色 + alpha 值顯示子元素。這僅用於 F5 預覽,因為 CGAL 和 STL (F6) 目前不支援顏色。alpha 值預設為 1.0(不透明),如果未指定。

函式簽名

[編輯 | 編輯原始碼]
color( c = [r, g, b, a] ) { ... }
color( c = [r, g, b], alpha = 1.0 ) { ... }
color( "#hexvalue" ) { ... }
color( "colorname", 1.0 ) { ... }

請注意,r, g, b, a 值限制為範圍 [0,1] 內的浮點數,而不是更傳統的整數 { 0 ... 255 }。但是,沒有什麼可以阻止你使用 {0 ... 255} 中的 R, G, B 值,並進行適當的縮放:color([ R/255, G/255, B/255 ]) { ... }

[注意: 需要版本 2011.12] 顏色也可以用名稱定義(不區分大小寫)。例如,要建立紅色球體,你可以寫 color("red") sphere(5);。Alpha 作為命名顏色的附加引數指定:color("Blue",0.5) cube(5);

[注意: 需要版本 2019.05] 十六進位制值可以用 4 種格式給出,#rgb#rgba#rrggbb#rrggbbaa。如果在十六進位制值和單獨的 alpha 引數中都給出了 alpha 值,則 alpha 引數優先。

警告: alpha 處理(透明度)對順序敏感。透明物體必須列在不透明物體之後才能正確顯示它們。某些涉及多個透明物體的組合無法正確處理。參見問題 #1390

可用的顏色名稱來自全球資訊網聯盟的 SVG 顏色列表。顏色名稱的圖表如下,
(請注意,灰色/灰色的兩種拼寫,包括石板灰色/石板灰色等都是有效的):

紫色
薰衣草
李子
紫羅蘭
蘭花
紫紅色
洋紅
中蘭花紫
中紫色
藍紫色
深紫色
暗蘭花紫
深洋紅
紫色
靛藍
深石板藍
石板藍
中石板藍
紅色
印度紅
淡珊瑚色
鮭魚色
深鮭魚色
淡鮭魚色
紅色
深紅色
火磚色
深紅色
藍色
水色
青色
淡青色
淡綠寶石色
海綠色
綠松石色
中綠松石色
深綠松石色
軍綠色
鋼藍色
淡鋼藍色
粉藍色
淡藍色
天藍色
淡天藍色
深天藍色
道奇藍
矢車菊藍
皇家藍
藍色
中藍色
深藍色
海軍藍
午夜藍
粉紅色
粉紅色
淡粉色
熱粉色
深粉色
中紫色紅
淡紫色紅
綠色
綠黃色
黃綠色
草綠色
酸橙色
青綠色
淡綠色
淺綠色
中等彈簧綠色
彈簧綠色
中等海綠色
海綠色
森林綠色
綠色
深綠色
黃綠色
橄欖褐色
橄欖色
深橄欖綠色
中等藍綠色
深海綠色
淺海綠色
深青色
青綠色
橙色
淡鮭魚色
珊瑚色
番茄色
橙紅色
深橙色
橙色
黃色
金色
黃色
淺黃色
檸檬薄紗
淺金黃色
木瓜色
鹿皮色
桃紅色
淡金黃色
卡其色
深卡其色
棕色
玉米色
淡杏仁色
淺褐色
納瓦霍白
小麥色
褐色
棕褐色
玫瑰棕色
沙棕色
金黃色
深金黃色
秘魯色
巧克力色
馬鞍棕色
赭石色
棕色
栗色
白色
白色
雪白色
蜜色
薄荷色
蔚藍色
淡藍色
幽靈白色
煙白色
貝殼色
米色
老蕾絲色
花白色
象牙色
古董白色
亞麻色
淡紫紅色
霧玫瑰色
灰色
淺灰色
淺灰色
銀色
深灰色
灰色
暗灰色
淺石板灰色
石板灰色
深石板灰色
黑色
三維多色正弦波

這是一個繪製波浪形多色物體的程式碼片段

  for(i=[0:36]) {
    for(j=[0:36]) {
      color( [0.5+sin(10*i)/2, 0.5+sin(10*j)/2, 0.5+sin(10*(i+j))/2] )
      translate( [i, j, 0] )
      cube( size = [1, 1, 11+10*cos(10*i)*sin(10*j)] );
    }
  }

↗ 由於 -1<=sin(x)<=1,則 0<=(1/2 + sin(x)/2)<=1,允許分配給顏色的 RGB 成分保持在 [0,1] 區間內。

基於維基百科“網路顏色”的圖表

在您想根據引數可選地設定顏色時,可以使用以下技巧

 module myModule(withColors=false) {
    c=withColors?"red":undef;
    color(c) circle(r=10);
 }

將顏色名稱設定為 undef 會保留預設顏色。

[注意: 需要版本 2015.03]

Offset 從現有輪廓生成一個新的 2d 內部或外部輪廓。有兩種操作模式:徑向和增量。

  • 徑向方法建立新的輪廓,就像某個半徑的圓圍繞原始輪廓的外部(r > 0)或內部(r < 0)旋轉一樣。
  • 增量方法建立一個新的輪廓,其邊與原始輪廓的固定距離向外(delta > 0)或向內(delta < 0)。

構造方法生成一個輪廓,該輪廓在原始輪廓的內部或外部。對於使用增量的輪廓,當輪廓繞過拐角時,可以給它提供一個可選的倒角。

Offset 透過從原始輪廓中減去負偏移構造,或從正偏移構造中減去原始輪廓來建立薄壁,非常有用。

Offset 可用於模擬一些常見的實體建模操作

  • 圓角:offset(r=-3) offset(delta=+3) 會將所有內部(凹)拐角圓角化,並保持平壁不變。但是,直徑小於 2*r 的孔會消失。
  • 圓形:offset(r=+3) offset(delta=-3) 會將所有外部(凸)拐角圓角化,並保持平壁不變。但是,厚度小於 2*r 的壁會消失。
引數

第一個引數可以不帶名稱傳遞,在這種情況下,它被視為下面的 r 引數。如果使用其他引數,則必須命名它們。

rdelta

數字。要偏移多邊形的量。為負值時,多邊形向內偏移。
  • r(如果未命名,則為預設引數)指定圍繞輪廓旋轉的圓的半徑,無論是在內部還是外部。此模式會生成圓角。名稱可以省略;即,offset(c) 等效於 offset(r=c)
  • delta 指定新輪廓與原始輪廓的距離,因此會複製角形拐角。在輪廓會與自身交叉的地方,不會生成任何向內的周長。
倒角
布林值。(預設值為 false)當使用 delta 引數時,此標誌定義邊是倒角(用直線切斷)還是不倒角(擴充套件到它們的交點)。此引數對徑向偏移沒有影響。

$fa$fs$fn

圓形解析度 特殊變數可用於控制徑向偏移生成的曲線的平滑度或面大小。它們對增量偏移沒有影響。
正 r/delta 值
負 r/delta 值
不同引數的結果。黑色多邊形是 offset() 操作的輸入。

示例

示例 1:結果。
// Example 1
 
linear_extrude(height = 60, twist = 90, slices = 60) {
   difference() {
     offset(r = 10) {
      square(20, center = true);
     }
     offset(r = 8) {
       square(20, center = true);
     }
   }
 }
// Example 2
 
module fillet(r) {
   offset(r = -r) {
     offset(delta = r) {
       children();
     }
   }
}


[注意: 需要版本 開發快照]

Fill 會移除多邊形的孔,而不會更改輪廓。對於凸多邊形,結果與 hull() 相同。

示例

示例 1:結果。
// Example 1
 
t = "OpenSCAD";

linear_extrude(15) {
	text(t, 50);
}
color("darkslategray") {
	linear_extrude(2) {
		offset(4) {
			fill() {
				text(t, 50);
			}
		}
	}
}

閔可夫斯基

[編輯 | 編輯原始碼]
一個盒子和一個圓柱體
盒子和圓柱體的閔可夫斯基和

顯示子節點的閔可夫斯基和

用法示例

假設您有一個扁平的盒子,並且想要一個圓角邊緣。有多種方法可以做到這一點(例如,請參閱下面的 hull),但閔可夫斯基很優雅。取您的盒子和一個圓柱體

 $fn=50;
 cube([10,10,1]);
 cylinder(r=2,h=1);

然後,對它們進行閔可夫斯基和(注意,盒子的外尺寸現在為 10+2+2 = 14 單位乘以 14 單位乘以 2 單位高,因為物件的 高度已相加)

$fn=50;
minkowski()
{
  cube([10,10,1]);
  cylinder(r=2,h=1);
}

注意:原點第二個物件的點用於加法。以下閔可夫斯基和是不同的:第一個從圓柱體中擴充套件原始立方體 +1 在 -x、+x、-y、+y 中,從圓柱體中擴充套件 0.5 單位在 -z、+z 中。第二個從圓柱體中擴充套件它 +1 在 -x、+x、-y、+y 和 +z 中,但在 -z 中擴充套件 0 單位從圓柱體中擴充套件。

minkowski() {
	cube([10, 10, 1]);
	cylinder(1, center=true);
}
minkowski() {
	cube([10, 10, 1]);
	cylinder(1);
}

警告:對於 $fn 的高值,閔可夫斯基和最終可能會消耗大量的 CPU 和記憶體,因為它必須將每個元素的每個子節點與每個其他元素的所有節點結合起來。所以,例如,如果 $fn=100 並且您組合了兩個圓柱體,那麼它不僅執行 200 次操作(就像兩個獨立的圓柱體一樣),而是執行 100*100 = 10000 次操作。

警告:如果其中一個輸入是複合的,例如

    {
         translate([0, 0, collar])
         sphere(ball);
         cylinder(collar, ball, ball);
    }

它可能被視為兩個獨立的輸入,導致輸出過大,並且表面之間具有應相對於彼此保持不變的特徵。如果是這樣,請使用 union()

兩個圓柱體
兩個圓柱體的凸包

顯示子節點的凸包

用法示例

hull() {
    translate([15,10,0]) circle(10);
    circle(10);
}

2D 物件的船體使用它們在 xy 平面上的投影(陰影),並在 xy 平面生成結果。它們的 Z 高度不會在操作中使用。

參考兩個圓柱體的凸包的圖示,在兩個 2D 圓上使用 hull() 並在 linear_extrude 上計算效率更高。將生成的 2D 形狀擠出到 3D 形狀,而不是在兩個圓柱體上使用 hull(),即使生成的物件看起來相同。涉及 hull() 的複雜幾何體可以透過在 2D 中開始,如果可能的話,以更快的速度渲染。

第 5 章 - 布林運算

[編輯 | 編輯原始碼]

OpenSCAD 使用者手冊/OpenSCAD 語言

布林運算概述

[編輯 | 編輯原始碼]
2D 示例
[編輯 | 編輯原始碼]
 union()       {square(10);circle(10);} // square or  circle
 difference()  {square(10);circle(10);} // square and not circle
 difference()  {circle(10);square(10);} // circle and not square
 intersection(){square(10);circle(10);} // square and circle
3D 示例
[編輯 | 編輯原始碼]
 union()       {cube(12, center=true); sphere(8);} // cube or  sphere
 difference()  {cube(12, center=true); sphere(8);} // cube and not sphere
 difference()  {sphere(8); cube(12, center=true);} // sphere and not cube
 intersection(){cube(12, center=true); sphere(8);} // cube and sphere

建立所有子節點的並集。這是所有子節點的總和(邏輯)。
可與 2D 或 3D 物件一起使用,但不要混合使用。

Union

 //Usage example:
 union() {
 	cylinder (h = 4, r=1, center = true, $fn=100);
 	rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100);
 }

說明:union 在未使用時是隱式的。但在 difference 中,必須使用 union 來將第一個子節點分組為一個,例如。

注意:對於所有並集,無論是顯式還是隱式,合併的外部面都必須不重合。不遵守此規則會導致設計行為未定義,並可能導致生成的模型非流形(包含零體積部分或反向部分),這通常會導致警告,有時還會導致部分設計從渲染輸出中移除。(這也會導致預覽過程中出現閃爍效果。)此要求不是錯誤,而是浮點比較的內在屬性以及無法準確表示如大多數旋轉產生的無理數的根本原因。例如,以下是一個無效的 OpenSCAD 程式,至少會在大多數平臺上導致警告。

 // Invalid!
 size = 10;
 rotation = 17;
 union() {
    rotate([rotation, 0, 0])
       cube(size);
    rotate([rotation, 0, 0])
       translate([0, 0, size])
       cube([2, 3, 4]);
 }

解決方案是在合併相鄰面時始終使用一個稱為 epsilon 的小值來保證重疊。請注意,在兩個位置使用了 0.01 的 eps 值,以便外部結果等效於預期結果。

 // Correct!
 size = 10;
 rotation = 17;
 eps = 0.01;
 union() {
    rotate([rotation, 0, 0])
       cube(size);
    rotate([rotation, 0, 0])
       translate([0, 0, size-eps])
       cube([2, 3, 4+eps]);
 }

從第一個子節點中減去第二個(以及所有後續)子節點(邏輯)。
可與 2D 或 3D 物件一起使用,但不要混合使用。

Difference

Usage example:
difference() {
	cylinder (h = 4, r=1, center = true, $fn=100);
	rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100);
}

注意:差集操作中要移除的表面必須重疊,並且要移除的負面部分必須完全延伸到它要移除其表面的體積之外。不遵守此規則會導致預覽偽像,並可能導致非流形渲染警告或渲染輸出中部分內容被移除。請參閱上面並集中的描述,瞭解為什麼需要這樣做,以及一個使用小的 epsilon 值來執行此操作的示例。

具有多個子節點的差集
[編輯 | 編輯原始碼]

注意,在第二個例項中,結果是添加了第一個和第二個子節點的並集。

// Usage example for difference of multiple children:
$fn=90;
difference(){
                                            cylinder(r=5,h=20,center=true);
    rotate([00,140,-45]) color("LightBlue") cylinder(r=2,h=25,center=true);
    rotate([00,40,-50])                     cylinder(r=2,h=30,center=true);
    translate([0,0,-10])rotate([00,40,-50]) cylinder(r=1.4,h=30,center=true);
}
   
// second instance with added union
translate([10,10,0]){
    difference(){
      union(){        // combine 1st and 2nd children
                                                cylinder(r=5,h=20,center=true);
        rotate([00,140,-45]) color("LightBlue") cylinder(r=2,h=25,center=true);
      }
      rotate([00,40,-50])                       cylinder(r=2,h=30,center=true);
      translate([0,0,-10])rotate([00,40,-50])   cylinder(r=1.4,h=30,center=true);
    }
}

建立所有子節點的交集。這保留了重疊部分(邏輯)。
僅保留所有子節點共有的或共享的區域。
可與 2D 或 3D 物件一起使用,但不要混合使用。

Intersection

//Usage example:
intersection() {
	cylinder (h = 4, r=1, center = true, $fn=100);
	rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100);
}


警告:使用渲染時,始終計算此樹的 CSG 模型(即使在 OpenCSG 預覽模式下)。這會使預覽非常緩慢,並且 OpenSCAD 似乎會掛起/凍結。

Usage example:
render(convexity = 1) { ... }
凸性 整數。凸性引數指定與物體相交的光線可能穿透的前後面數量的最多數量。此引數僅在 OpenCSG 預覽模式下正確顯示物體時才需要,對多面體渲染沒有影響。


此影像顯示了一個凸性為 4 的二維形狀,因為紅色指示的光線與二維形狀最多相交 4 次。三維形狀的凸性將以類似方式確定。將其設定為 10 對於大多數情況應該可以正常工作。

第 6 章 - 其他函式和運算子

[編輯 | 編輯原始碼]

OpenSCAD 使用者手冊/OpenSCAD 語言

條件和迭代函式

[編輯 | 編輯原始碼]

for 迴圈

[編輯 | 編輯原始碼]

評估範圍或向量中的每個值,將其應用於以下操作。

 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>
巢狀 3 層的 for() 迴圈
 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();}
使用向量向量的示例
示例 1 for() 迴圈向量向量(旋轉)
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);
}


示例 2 for() 迴圈向量向量(平移)
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);
}
示例 3 for() 迴圈向量向量
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 迴圈

[編輯 | 編輯原始碼]

遍歷範圍或向量中的值,並建立由每次傳遞建立的物件的交集

除了為每次傳遞建立獨立的例項之外,標準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);
    }
}
intersection_for()
intersection() for() 或 for() intersection()


示例 2 - 旋轉:
 intersection_for(i = [ [  0,  0,   0],
 			[ 10, 20, 300],
 			[200, 40,  57],
 			[ 20, 88,  57] ])
{
    rotate(i)
    cube([100, 20, 20], center = true);
}
intersection_for()
intersection() for()

If 語句

[編輯 | 編輯原始碼]

執行測試以確定子範圍內的操作是否應執行。

非常重要。你無法更改變數的值。如果你在括號內更新變數的值,新值將在你退出該範圍時丟失。

if (test) scope1
if (test){scope1}
if (test) scope1  else  scope2
if (test){scope1} else {scope2}
引數
測試:通常是一個布林表示式,但可以是任何值或變數。
請參閱此處瞭解值的真或假狀態。
請參閱此處瞭解布林和邏輯運算子。
不要將賦值運算子 '=' 與相等運算子 '==' 混淆。
範圍 1:測試為時要執行的一個或多個操作。
範圍 2:測試為時要執行的一個或多個操作。
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}

請注意,elseif 是兩個單獨的單詞。當向下處理測試鏈時,第一個真值使用其範圍。所有後續測試都將跳過。

示例
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);}

條件?

[編輯 | 編輯原始碼]

一個使用測試來確定要返回哪個值的函式。

 a =   test ? TrueValue : FalseValue ;
 echo( test ? TrueValue : FalseValue );
引數
測試:通常是一個布林表示式,但可以是任何值或變數。
請參閱此處瞭解值的真或假狀態。
請參閱此處瞭解布林和邏輯運算子。
不要將賦值 '=' 與相等 '==' 混淆。
TrueValue:測試為時要返回的值。
FalseValue:測試為時要返回的值。
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);
}

Let 語句

[編輯 | 編輯原始碼]

[注意: 需要 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);
    }
}

數學運算子

[編輯 | 編輯原始碼]

標量算術運算子

[編輯 | 編輯原始碼]

標量算術運算子以數字作為運算元,並生成一個新數字。

+ 加法
- 減法
* 乘法
/ 除法
% 模運算
^ 指數 [注意: 需要 2021.01 版本]

- 也可以用作字首運算子來否定一個數字。

在 2021.01 版本之前,使用內建數學函式 pow() 而不是 ^ 指數運算子。

 ?  條件運算子
使用示例
a=[for(i=[0:10])i%2];
echo(a);//ECHO: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

for(i=[0:10]) translate([i,i%2?0:5])cube(1); // move every even up

餘數為 0 或 1 偶數/奇數

關係運算符

[編輯 | 編輯原始碼]

關係運算符從兩個運算元生成布林結果。

< 小於
<= 小於或等於
== 等於
!= 不等於
>= 大於或等於
> 大於

如果兩個運算元都是簡單數字,則含義不言而喻。

如果兩個運算元都是字串,則字母排序決定相等性和順序。例如,"ab" > "aa" > "a"。

如果兩個運算元都是布林值,則 true > false。在布林值和數字之間的不等式比較中,true 被視為 1,false 被視為 0。涉及布林值的其它不等式測試返回 false。

如果兩個運算元都是向量,則當向量相同時,相等性測試返回 true,否則返回 false。涉及一個或兩個向量的不等式測試總是返回 false,因此例如 [1] < [2] 為 false

不同型別總是使用 '==' 和 '!=' 測試為不相等。不同型別之間的不等式比較(除了上面提到的布林值和數字外)總是導致 false。請注意,[1] 和 1 是不同型別,因此 [1] == 1 為 false。

undef 不等於任何東西,除了 undef。涉及 undef 的不等式比較導致 false

nan 不等於任何東西(甚至不等於自身),並且所有不等式測試都產生 false。參見 數字

邏輯運算子

[編輯 | 編輯原始碼]

所有邏輯運算子都以布林值作為運算元,併產生一個布林值。非布林值在運算子計算之前被轉換為布林值。

&& 邏輯與
|| 邏輯或
! 邏輯一元非

由於 [false]true,因此 false || [false] 也為 true

邏輯運算子對向量的處理方式不同於關係運算符

[1, 1] > [0, 2]false,但

[false, false] && [false, false]true

條件運算子

[編輯 | 編輯原始碼]

?:運算子可以用於有條件地計算一個或另一個表示式。它的工作方式與?:來自 C 類程式語言系列的運算子。

 ?  條件運算子
使用示例
a=1;
b=2;
c= a==b ? 4 : 5;

如果 a 等於 b,則 c 設定為 4,否則 c 設定為 5。
部分 "a==b" 必須是計算結果為布林值的內容。

向量-數字運算子

[編輯 | 編輯原始碼]

向量-數字運算子以向量和數字作為運算元,並生成一個新向量。

* 將所有向量元素乘以數字
/ 將所有向量元素除以數字
示例
L = [1, [2, [3, "a"] ] ];
echo(5*L);
// ECHO: [5, [10, [15, undef]]]

向量運算子

[編輯 | 編輯原始碼]

向量運算子以向量作為運算元,並生成一個新向量。

+ 逐元素加法
- 逐元素減法

- 也可以用作字首運算子來逐元素否定一個向量。

示例
L1 = [1, [2, [3, "a"] ] ];
L2 = [1, [2, 3] ];
echo(L1+L1); // ECHO: [2, [4, [6, undef]]]
echo(L1+L2); // ECHO: [2, [4, undef]]

使用 + 或 - 和大小不同的向量運算元會生成一個結果向量,該結果向量的尺寸與較小向量相同。

向量點積運算子

[編輯 | 編輯原始碼]

如果乘法的兩個運算元都是簡單向量,則結果將根據 點積 的線性代數規則生成一個數字。c = u*v; 導致 。如果運算元的大小不匹配,則結果為 undef

矩陣乘法

[編輯 | 編輯原始碼]

如果乘法的運算元之一或兩者都是矩陣,則結果將根據 矩陣積 的線性代數規則生成一個簡單向量或矩陣。在下文中,A, B, C... 是矩陣,u, v, w... 是向量。下標 i, j 表示元素索引。

對於大小為 n × m 的矩陣 A 和大小為 m × p 的矩陣 B,它們的積 C = A*B; 是一個大小為 n × p 的矩陣,其元素為

.

C = B*A; 導致 undef,除非 n = p

對於大小為 n × m 的矩陣 A 和大小為 m 的向量 v,它們的乘積 u = A*v; 是一個大小為 n 的向量,其元素為

.

線上性代數中,這是 矩陣和列向量的乘積

對於大小為 n 的向量 v 和大小為 n × m 的矩陣 A,它們的乘積 u = v*A; 是一個大小為 m 的向量,其元素為

.

線上性代數中,這是行向量和矩陣的乘積。

矩陣乘法不滿足交換律: .

數學函式

[edit | edit source]

三角函式

[edit | edit source]

三角函式使用 C 語言的數學函式,這些函式又基於二進位制浮點數學,在計算過程中使用實數的近似值。OpenSCAD 的數學函式使用 C++ 的 'double' 型別,在 Value.h/Value.cc 內部,

有關 C 庫數學函式的具體細節,例如有效輸入/輸出範圍,可以在 Open Group 網站找到 math.h & acos

數學 餘弦 函式,以度為單位。參見 餘弦

引數

<degrees>
十進位制數。以度為單位的角度。
用法示例
 for(i=[0:36])
    translate([i*10,0,0])
       cylinder(r=5,h=cos(i*10)*50+60);
OpenSCAD 餘弦函式‎

數學 正弦 函式。參見 正弦

引數

<degrees>
十進位制數。以度為單位的角度。
使用示例 1
 for (i = [0:5]) {
  echo(360*i/6, sin(360*i/6)*80, cos(360*i/6)*80);
   translate([sin(360*i/6)*80, cos(360*i/6)*80, 0 ])
    cylinder(h = 200, r=10);
 }
使用示例 2
 for(i=[0:36])
    translate([i*10,0,0])
       cylinder(r=5,h=sin(i*10)*50+60);
OpenSCAD 正弦函式

數學 正切 函式。參見 正切

引數

<degrees>
十進位制數。以度為單位的角度。
用法示例
 for (i = [0:5]) {
  echo(360*i/6, tan(360*i/6)*80);
   translate([tan(360*i/6)*80, 0, 0 ])
    cylinder(h = 200, r=10);
 }

數學 反餘弦,或 餘弦的逆函式,以度為單位表示。參見:反三角函式

數學 反正弦,或 正弦的逆函式,以度為單位表示。參見:反三角函式

數學 反正切,或 正切的逆函式,函式。返回 x 的反正切函式的主值,以度為單位表示。atan 無法區分 y/x 和 -y/-x,返回 -90 到 +90 之間的角度。參見:atan2 以及 反三角函式

atan2

[edit | edit source]

數學 二引數反正切 函式 atan2(y,x),範圍涵蓋完整的 360 度。此函式以度為單位返回 x 軸和向量 (x,y) 之間的完整角度 (0-360)。

使用示例

atan2(5.0,-5.0);     //result: 135 degrees. atan() would give -45
atan2(y,x);          //angle between (1,0) and (x,y) = angle around z-axis

其他數學函式

[edit | edit source]

數學 絕對值 函式。返回帶符號十進位制數的正值。

使用示例

abs(-5.0);  returns 5.0
abs(0);     returns 0.0
abs(8.0);   returns 8.0

數學 向上取整 函式。

返回下一個最高的整數,如果需要則向上舍入值。

參見:向上取整函式

echo(ceil(4.4),ceil(-4.4));     // produces ECHO: 5, -4

concat

[edit | edit source]

[注意: 需要版本 2015.03]

返回一個新向量,該向量是將提供的向量的元素追加後的結果。

如果引數是一個向量,則向量的元素將被逐個附加到結果向量中。在這種情況下,字串與向量不同。

使用示例

echo(concat("a","b","c","d","e","f"));          // produces ECHO: ["a", "b", "c", "d", "e", "f"]
echo(concat(["a","b","c"],["d","e","f"]));      // produces ECHO: ["a", "b", "c", "d", "e", "f"]
echo(concat(1,2,3,4,5,6));                      // produces ECHO: [1, 2, 3, 4, 5, 6]

向量組

echo(concat([ [1],[2] ], [ [3] ]));             // produces ECHO: [[1], [2], [3]]

注意:傳遞給函式的所有向量都會降低一個巢狀級別。當新增類似單個元素 [x, y, z] 元組(也是向量)的東西時,元組需要用向量括起來(即額外的括號)才能進行拼接。在下面的例子中,第四個點被新增到多邊形路徑中,該路徑以前類似於一個三角形,現在它變成了一個正方形。

polygon(concat([[0,0],[0,5],[5,5]], [[5,0]]));

與字串對比

echo(concat([1,2,3],[4,5,6]));                   // produces ECHO: [1, 2, 3, 4, 5, 6]
echo(concat("abc","def"));                       // produces ECHO: ["abc", "def"]
echo(str("abc","def"));                          // produces ECHO: "abcdef"

計算兩個向量在 3D 或 2D 空間中的叉積。如果兩個向量都在 3D 空間中,結果將是一個垂直於這兩個輸入向量的向量。如果兩個向量都在 2D 空間中,它們的叉積的形式為 [0,0,z],叉積函式只返回叉積的 z 值。

cross([x,y], [u,v]) = x*v - y*u

請注意,這是 2x2 矩陣 [[x,y],[u,v]] 的行列式。使用任何其他型別、長度不同於 2 或 3 的向量,或者長度不一致的向量會導致 'undef'。

使用示例

echo(cross([2, 3, 4], [5, 6, 7]));     // produces ECHO: [-3, 6, -3]
echo(cross([2, 1, -3], [0, 4, 5]));    // produces ECHO: [17, -10, 8]
echo(cross([2, 1], [0, 4]));           // produces ECHO: 8
echo(cross([1, -3], [4, 5]));          // produces ECHO: 17
echo(cross([2, 1, -3], [4, 5]));       // produces ECHO: undef
echo(cross([2, 3, 4], "5"));           // produces ECHO: undef

對於 2D 或 3D 中的任意兩個向量 ab,以下成立:

cross(a,b) == -cross(b,a)

指數函式

[編輯 | 編輯原始碼]

數學 exp 函式。返回 x 的以 e 為底的指數函式,即 e 的 x 次方。參見:指數

echo(exp(1),exp(ln(3)*4));    // produces ECHO: 2.71828, 81

向下取整

[編輯 | 編輯原始碼]

數學 floor 函式。floor(x) = 不大於 x 的最大整數。

參見:向下取整函式

echo(floor(4.4),floor(-4.4));    // produces ECHO: 4, -5

自然對數

[編輯 | 編輯原始碼]

數學 自然對數。參見:自然對數

數學 長度 函式。返回陣列、向量或字串引數的長度。

使用示例

str1="abcdef"; len_str1=len(str1);
echo(str1,len_str1);

a=6; len_a=len(a);
echo(a,len_a);

array1=[1,2,3,4,5,6,7,8]; len_array1=len(array1);
echo(array1,len_array1);

array2=[[0,0],[0,1],[1,0],[1,1]]; len_array2=len(array2);
echo(array2,len_array2);

len_array2_2=len(array2[2]);
echo(array2[2],len_array2_2);

結果

WARNING: len() parameter could not be converted in file , line 4
ECHO: "abcdef", 6
ECHO: 6, undef
ECHO: [1, 2, 3, 4, 5, 6, 7, 8], 8
ECHO: [[0, 0], [0, 1], [1, 0], [1, 1]], 4
ECHO: [1, 0], 2

此函式允許(例如)解析陣列、向量或字串。

使用示例

str2="4711";
for (i=[0:len(str2)-1])
	echo(str("digit ",i+1,"  :  ",str2[i]));

結果

ECHO: "digit 1  :  4"
ECHO: "digit 2  :  7"
ECHO: "digit 3  :  1"
ECHO: "digit 4  :  1"

請注意,當簡單變數作為引數傳遞時,len() 函式未定義並會引發警告。

這在處理模組引數時很有用,類似於形狀可以定義為單個數字,也可以定義為 [x,y,z] 向量;例如 cube(5) 或 cube([5,5,5])。

例如

module doIt(size) {
	if (len(size) == undef) {
		// size is a number, use it for x,y & z. (or could be undef)
		do([size,size,size]);
	} else { 
		// size is a vector, (could be a string but that would be stupid)
		do(size);
	}
 }
 
doIt(5);	// equivalent to [5,5,5]
doIt([5,5,5]);	// similar to cube(5) v's cube([5,5,5])

[注意: 需要版本 2015.03]

在表示式中對變數進行順序賦值。以下表達式在 let 賦值的上下文中進行計算,並且可以使用這些變數。這主要用於透過將中間結果賦值給變數來使複雜的表示式更易讀。

引數

let (var1 = value1, var2 = f(var1), var3 = g(var1, var2)) expression

用法示例

echo(let(a = 135, s = sin(a), c = cos(a)) [ s, c ]); // ECHO: [0.707107, -0.707107]

Let 也可以用來在 函式 中建立變數。 (另請參見: "Let 語句")

對數函式

[編輯 | 編輯原始碼]

數學 對數,以 10 為底。例如:log(1000) = 3。參見:對數

查詢函式

[編輯 | 編輯原始碼]

在表中查詢值,如果不存在完全匹配的值,則進行線性插值。第一個引數是要查詢的值。第二個是查詢表——一個鍵值對向量。

引數

查詢鍵
<key,value> 陣列
鍵和值

存在一個錯誤,即超出範圍的鍵將返回列表中的第一個值。更新版本的 Openscad 應該使用表的頂端或底端,而不是使用第一個值。

用法示例: 建立一個由不同高度的圓柱體組成的 3D 圖表。

 function get_cylinder_h(p) = lookup(p, [
 		[ -200, 5 ],
 		[ -50, 20 ],
 		[ -20, 18 ],
 		[ +80, 25 ],
 		[ +150, 2 ]
 	]);
 
 for (i = [-100:5:+100]) {
 	// echo(i, get_cylinder_h(i));
 	translate([ i, 0, -30 ]) cylinder(r1 = 6, r2 = 2, h = get_cylinder_h(i)*3);
 }
OpenSCAD 查詢函式

最大值

[編輯 | 編輯原始碼]

返回引數中的最大值。如果給定單個向量作為引數,則返回該向量的最大元素。

引數

max(n,n{,n}...)
max(vector)
<n>
兩個或多個小數
<vector>
單個小數向量 [注意: 需要版本 2014.06].

用法示例

max(3.0,5.0)
max(8.0,3.0,4.0,5.0)
max([8,3,4,5])

結果

5
8
8

最小值

[編輯 | 編輯原始碼]

返回引數中的最小值。如果給定單個向量作為引數,則返回該向量的最小元素。

引數

min(n,n{,n}...)
min(vector)
<n>
兩個或多個小數
<vector>
單個小數向量 [注意: 需要版本 2014.06].

用法示例

min(3.0,5.0)
min(8.0,3.0,4.0,5.0)
min([8,3,4,5])

結果

3
3
3

取模運算

[編輯 | 編輯原始碼]

僅出於清晰度而包含在此文件中。OpenSCAD 中的 '取模' 操作以運算子 % 存在,而不是以函式形式存在。參見 取模運算子 (%)

返回向量的 歐幾里得範數。請注意,這將返回實際的數字長度,而 len 將返回向量或陣列中的元素數量。

使用示例

a=[1,2,3,4];
b="abcd";
c=[];
d="";
e=[[1,2,3,4],[1,2,3],[1,2],[1]];
echo(norm(a)); //5.47723
echo(norm(b)); //undef
echo(norm(c)); //0
echo(norm(d)); //undef
echo(norm(e[0])); //5.47723
echo(norm(e[1])); //3.74166
echo(norm(e[2])); //2.23607
echo(norm(e[3])); //1

結果

ECHO: 5.47723
ECHO: undef
ECHO: 0
ECHO: undef
ECHO: 5.47723
ECHO: 3.74166
ECHO: 2.23607
ECHO: 1

冪函式

[編輯 | 編輯原始碼]

數學 函式。

從版本 2021.01 開始,可以使用 指數運算子 ^ 替代。

引數

<base>
小數。底數。
<exponent>
小數。指數。

使用示例

for (i = [0:5]) {
 translate([i*25,0,0]) {
   cylinder(h = pow(2,i)*5, r=10);
   echo (i, pow(2,i));
 }
}
echo(pow(10,2)); // means 10^2 or 10*10
// result: ECHO: 100

echo(pow(10,3)); // means 10^3 or 10*10*10
// result: ECHO: 1000

echo(pow(125,1/3)); // means 125^(0.333...), which calculates the cube root of 125
// result: ECHO: 5

隨機數生成器

[編輯 | 編輯原始碼]

隨機數生成器。生成一個偽隨機數的常量向量,非常類似於陣列。這些數字是雙精度浮點數,而不是整數。當只生成一個數字時,仍然使用 variable[0] 呼叫它。

引數

min_value
隨機數範圍的最小值
max_value
隨機數範圍的最大值
value_count
要作為向量返回的隨機數數量
seed_value (可選)
隨機數生成器的種子值,用於生成可重複的結果。在 2015 年後期之前的版本中,seed_value 會被四捨五入到最接近的整數。

使用示例

// get a single number
single_rand = rands(0,10,1)[0];
echo(single_rand);
// get a vector of 4 numbers
seed=42;
random_vect=rands(5,15,4,seed);
echo( "Random Vector: ",random_vect);
sphere(r=5);
for(i=[0:3]) {
 rotate(360*i/4) {
   translate([10+random_vect[i],0,0])
     sphere(r=random_vect[i]/2);
 }
}
// ECHO: "Random Vector: ", [8.7454, 12.9654, 14.5071, 6.83435]

四捨五入

[編輯 | 編輯原始碼]

"round" 運算子分別返回最大或最小整數部分,具體取決於數值輸入是正數還是負數。

使用示例

round(5.4);
round(5.5);
round(5.6);
round(-5.4);
round(-5.5);
round(-5.6);

結果

5
6
6
-5
-6
-6

符號函式

[編輯 | 編輯原始碼]

數學 符號 函式。返回一個單位值,該值提取值的符號,參見:符號函式

引數

<x>
小數。要查詢符號的值。

使用示例

sign(-5.0);
sign(0);
sign(8.0);

結果

-1.0
0.0
1.0

平方根函式

[edit | edit source]

數學上的平方根函式。

用法示例
translate([sqrt(100),0,0])sphere(100);

無窮大和 NaN

[edit | edit source]

OpenSCAD 如何處理像 (1/0) 這樣的輸入?基本上,它的行為繼承自 OpenSCAD 所用語言 C++ 語言及其浮點數型別和相關的 C 數學庫。此係統允許透過特殊值“Inf”或“-Inf”來表示正無窮大和負無窮大。它還允許將像 sqrt(-1) 或 0/0 這樣的值表示為“NaN”,它是“非數字”的縮寫。可以在網上找到解釋,例如Open Group 關於 math.h 的網站維基百科關於 IEEE 754 數字格式的頁面。但是,OpenSCAD 是它自己的語言,因此它可能並不完全匹配 C 中發生的所有事情。例如,OpenSCAD 使用度而不是弧度來表示三角函式。另一個例子是 sin() 在輸入為 1/0 時不會丟擲“域錯誤”,儘管它確實返回 NaN。

以下是一些 OpenSCAD 數學函式的無限輸入示例及其在 2015 年底 OpenSCAD 迴歸測試系統中獲得的結果。

0/0: nan sin(1/0): nan asin(1/0): nan ln(1/0): inf round(1/0): inf
-0/0: nan cos(1/0): nan acos(1/0): nan ln(-1/0): nan round(-1/0): -inf
0/-0: nan tan(1/0): nan atan(1/0): 90 log(1/0): inf sign(1/0): 1
1/0: inf ceil(-1/0): -inf atan(-1/0): -90 log(-1/0): nan sign(-1/0): -1
1/-0: -inf ceil(1/0): inf atan2(1/0, -1/0): 135 max(-1/0, 1/0): inf sqrt(1/0): inf
-1/0: -inf floor(-1/0): -inf exp(1/0): inf min(-1/0, 1/0): -inf sqrt(-1/0): nan
-1/-0: inf floor(1/0): inf exp(-1/0): 0 pow(2, 1/0): inf pow(2, -1/0): 0

字串函式

[edit | edit source]

將所有引數轉換為字串並連線起來。

使用示例

number=2;
echo ("This is ",number,3," and that's it.");
echo (str("This is ",number,3," and that's it."));

結果

ECHO: "This is ", 2, 3, " and that's it."
ECHO: "This is 23 and that's it."

這可以用於將數字簡單地轉換為字串。

s = str(n); 

[注意: 需要版本 2015.03]

將數字轉換為包含對應程式碼的字元的字串。OpenSCAD 使用 Unicode,因此該數字被解釋為 Unicode 程式碼點。超出有效程式碼點範圍的數字將生成空字串。

引數

chr(數字)
如果程式碼點有效,則將一個程式碼點轉換為長度為 1 的字串(位元組數取決於 UTF-8 編碼)。
chr(向量)
將引數向量中給出的所有程式碼點轉換為字串。
chr(範圍)
將範圍引數產生的所有程式碼點轉換為字串。

示例

echo(chr(65), chr(97));      // ECHO: "A", "a"
echo(chr(65, 97));           // ECHO: "Aa"
echo(chr([66, 98]));         // ECHO: "Bb"
echo(chr([97 : 2 : 102]));   // ECHO: "ace"
echo(chr(-3));               // ECHO: ""
echo(chr(9786), chr(9788));  // ECHO: "☺", "☼"
echo(len(chr(9788)));        // ECHO: 1

注意:當與 echo() 一起使用時,控制檯輸出的字元程式碼大於 127 時,取決於平臺。

[注意: 需要 2019.05 版本]

將字元轉換為表示Unicode程式碼點的數字。如果引數不是字串,則 ord() 返回 undef

引數

ord(字串)
將給定字串的第一個字元轉換為 Unicode 程式碼點。

示例

echo(ord("a"));
// ECHO: 97

echo(ord("BCD"));
// ECHO: 66

echo([for (c = "Hello! 🙂") ord(c)]);
// ECHO: [72, 101, 108, 108, 111, 33, 32, 128578]

txt="1";
echo(ord(txt)-48,txt);
// ECHO: 1,"1" // only converts 1 character

返回文字中的字元數。

echo(len("Hello world"));    // 11

另見 search()

[edit | edit source]

search() 用於文字搜尋。

is_string(value)

[edit | edit source]

如果 value 是字串,則函式 is_string(value) 返回 true,否則返回 false。

echo(is_string("alpha")); //true
echo(is_string(22)); //false

使用者定義函式

[edit | edit source]

為了補充原生函式,您可以定義自己的函式,以下是一些建議。

//-- Lower case all chars of a string -- does not work with accented characters
function strtolower (string) = 
  chr([for(s=string) let(c=ord(s)) c<91 && c>64 ?c+32:c]); 

//-- Replace char(not string) in a string  
function char_replace (s,old=" ",new="_") = 
  chr([for(i=[0:len(s)-1]) s[i]==old?ord(new):ord(s[i])]);

//-- Replace last chars of a string (can be used for file extension replacement of same length)
function str_rep_last (s,new=".txt") = 
  str(chr([for(i=[0 :len(s)-len(new)-1])ord(s[i])]),new);

//-- integer value from string ---------- 
//Parameters ret and i are for function internal use (recursion)
function strtoint (s, ret=0, i=0) =
  i >= len(s)
  ? ret
  : strtoint(s, ret*10 + ord(s[i]) - ord("0"), i+1);

請注意這裡使用 chr() 從由其 ASCII 程式碼定義的未知數量的字元重新組合字串。這避免了在列表管理出現之前需要使用遞迴模組。

列表推導

[edit | edit source]

[注意: 需要版本 2015.03]

基本語法

[edit | edit source]

列表推導提供了一種靈活的方法來使用通用語法生成列表。

 [ list-definition expression ]

以下元素支援用於構建列表定義。

for (i = sequence)
遍歷範圍或現有列表。
for (init;condition;next)
以 C 風格的 for 表示的簡單遞迴呼叫。
each
以序列值作為引數,並將每個元素新增到正在構建的列表中。each x 等效於 `for (i = x) i`。
if (condition)
選擇標準,當為真時計算表示式並將其新增到結果列表中。
let (x = value)
區域性變數賦值。

多個生成器表示式

[edit | edit source]

[注意: 需要 2019.05 版本]

列表推導語法已推廣以允許使用多個表示式。這允許輕鬆地從由不同列表推導表示式生成的多個子列表構建列表,從而避免使用 concat。

steps = 50;

points = [
	// first expression generating the points in the positive Y quadrant
	for (a = [0 : steps]) [ a, 10 * sin(a * 360 / steps) + 10 ],
	// second expression generating the points in the negative Y quadrant
	for (a = [steps : -1 : 0]) [ a, 10 * cos(a * 360 / steps) - 20 ],
	// additional list of fixed points
	[ 10, -3 ], [ 3, 0 ], [ 10, 3 ]
];

polygon(points);

for 元素定義了列表生成的輸入值。語法與 for 迭代器使用的語法相同。等號右側的序列可以是任何列表。for 元素遍歷列表的所有成員。等號左側的變數依次採用序列中每個成員的值。然後可以在 for 元素的子級中處理此值,並且每個結果都成為所產生的最終列表的成員。

如果序列具有多個維度,for 將僅遍歷第一個維度。可以透過巢狀 for 元素訪問更深的維度。

此處介紹了一些常見的用法模式。

[ for (i = [start : step : end]) i ]
根據範圍定義生成輸出,此版本主要用於計算列表值或使用範圍值作為索引來訪問現有列表。

示例

// generate a list with all values defined by a range
list1 = [ for (i = [0 : 2 : 10]) i ];
echo(list1); // ECHO: [0, 2, 4, 6, 8, 10]
// extract every second character of a string
str = "SomeText";
list2 = [ for (i = [0 : 2 : len(str) - 1]) str[i] ];
echo(list2); // ECHO: ["S", "m", "T", "x"]
// indexed list access, using function to map input values to output values
function func(x) = x < 1 ? 0 : x + func(x - 1);
input = [1, 3, 5, 8];
output = [for (a = [ 0 : len(input) - 1 ]) func(input[a]) ];
echo(output); // ECHO: [1, 6, 15, 36]
[ for (i = [a, b, c, ...]) i ]
使用列表引數作為輸入,此版本可以用來將輸入值對映到計算後的輸出值。

示例

// iterate over an existing list
friends = ["John", "Mary", "Alice", "Bob"];
list = [ for (i = friends) len(i)];
echo(list); // ECHO: [4, 4, 5, 3]
// map input list to output list
list = [ for (i = [2, 3, 5, 7, 11]) i * i ];
echo(list); // ECHO: [4, 9, 25, 49, 121]
// calculate Fibonacci numbers
function func(x) = x < 3 ? 1 : func(x - 1) + func(x - 2);
input = [7, 10, 12];
output = [for (a = input) func(a) ];
echo(output); // ECHO: [13, 55, 144]
[ for (c = "String") c ]
根據字串生成輸出,這將遍歷字串的每個字元。

[注意: 需要 2019.05 版本]

示例

echo([ for (c = "String") c ]);
// ECHO: ["S", "t", "r", "i", "n", "g"]
[ for (a = inita, b = initb, ...;condition;a = nexta, b = nextb, ...) expr ]
用於以 c 風格的 for 迴圈表達簡單遞迴呼叫的生成器。

[注意: 需要 2019.05 版本]

此生成器的遞迴等效項為

function f(a, b, ...) =
    condition
    ? concat([expr], f(nexta, nextb, ...))
    : [];
  f(inita, initb, ...)

示例

echo( [for (a = 0, b = 1;a < 5;a = a + 1, b = b + 2) [ a, b * b ] ] );
// ECHO: [[0, 1], [1, 9], [2, 25], [3, 49], [4, 81]]

// Generate fibonacci sequence
echo([for (a = 0, b = 1;a < 1000;x = a + b, a = b, b = x) a]);
// ECHO: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]

// Cumulative sum of values in v
function cumsum(v) = [for (a = v[0]-v[0], i = 0; i < len(v); a = a+v[i], i = i+1) a+v[i]];
echo(cumsum([1, 2, 3, 4]));
// ECHO: [1, 3, 6, 10]
echo(cumsum([[1, 1], [2, 2], [3, 3]]));
// ECHO: [[1, 1], [3, 3], [6, 6]]

[注意: 需要 2019.05 版本]

each 直接嵌入作為引數提供的列表的值,有效地解開了引數列表。

// Without using "each", a nested list is generated
echo([ for (a = [1 : 4]) [a, a * a] ]);
// ECHO: [[1, 1], [2, 4], [3, 9], [4, 16]]

// Adding "each" unwraps the inner list, producing a flat list as result
echo([ for (a = [1 : 4]) each [a, a * a] ]);
// ECHO: [1, 1, 2, 4, 3, 9, 4, 16]

each 解開範圍,並在與多個生成器表示式結合使用時有助於構建更通用的 for 列表。

A = [-2, each [1:2:5], each [6:-2:0], -1];
echo(A);
// ECHO: [-2, 1, 3, 5, 6, 4, 2, 0, -1]
echo([ for (a = A) 2 * a ]);
// ECHO: [-4, 2, 6, 10, 12, 8, 4, 0, -2]

if 元素允許在表示式是否應該被分配並新增到結果列表中進行選擇。在最簡單的情況下,這允許對列表進行過濾。

[ for (i = list) if (condition(i)) i ]
當條件的評估結果為真時,表示式 i 會被新增到結果列表中。

示例

list = [ for (a = [ 1 : 8 ]) if (a % 2 == 0) a ];
echo(list); // ECHO: [2, 4, 6, 8]

請注意,if 元素不能位於表示式內部,它應該位於最頂層。

示例

// from the input list include all positive odd numbers
// and also all even number divided by 2

list = [-10:5];
echo([for(n=list) if(n%2==0 || n>=0) n%2==0 ? n/2 : n ]); 
// ECHO: [-5, -4, -3, -2, -1, 0, 1, 1, 3, 2, 5]
// echo([for(n=list) n%2==0 ? n/2 : if(n>=0) n ]); // this would generate a syntactical error

[注意: 需要 2019.05 版本]

if-else 結構等效於條件表示式 ?:,除了它可以與 filter if 結合使用。

[ for (i = list) if (condition(i)) x else y ]
當條件的評估結果為真時,表示式 x 會被新增到結果列表中,否則表示式 y 會被新增到結果列表中。
// even numbers are halved, positive odd numbers are preserved, negative odd numbers are eliminated
echo([for (a = [-3:5]) if (a % 2 == 0) [a, a/2] else if (a > 0) [a, a] ]);
// ECHO: [[-2, -1], [0, 0], [1, 1], [2, 1], [3, 3], [4, 2], [5, 5]];

請注意,在上面的表示式中,條件運算子不能替代 if-else。可以使用條件運算子來表達相同的過濾器,但邏輯更加隱晦。

// even numbers are halved, positive odd numbers are preserved, negative odd numbers are eliminated
echo([for (a = [-3:5]) if (a % 2 == 0 || (a % 2 != 0 && a > 0)) a % 2 == 0 ? [a, a / 2] : [a, a] ]);
// ECHO: [[-2, -1], [0, 0], [1, 1], [2, 1], [3, 3], [4, 2], [5, 5]];

要將 else 表示式繫結到特定的 if,可以使用括號。

// even numbers are dropped, multiples of 4 are substituted by -1 
echo([for(i=[0:10]) if(i%2==0) (if(i%4==0) -1 ) else i]);
// ECHO: [-1, 1, 3, -1, 5, 7, -1, 9]

// odd numbers are dropped, multiples of 4 are substituted by -1 
echo([for(i=[0:10]) if(i%2==0) if(i%4==0) -1 else i]);
// ECHO: [-1, 2, -1, 6, -1, 10]

let 元素允許在列表理解定義中對變數進行順序賦值。

[ for (i = list) let (assignments) a ]

示例

list = [ for (a = [ 1 : 4 ]) let (b = a*a, c = 2 * b) [ a, b, c ] ];
echo(list); // ECHO: [[1, 1, 2], [2, 4, 8], [3, 9, 18], [4, 16, 32]]

巢狀迴圈

[編輯 | 編輯原始碼]

有不同的方法來定義巢狀迴圈。在一個 for 元素中定義多個迴圈變數,以及多個 for 元素,都會產生扁平的結果列表。為了生成巢狀結果列表,需要額外的 [ ] 標記。

// nested loop using multiple variables
flat_result1 = [ for (a = [ 0 : 2 ], b = [ 0 : 2 ]) a == b ? 1 : 0 ];
echo(flat_result1); // ECHO: [1, 0, 0, 0, 1, 0, 0, 0, 1]


// nested loop using multiple for elements
flat_result2 = [ for (a = [ 0 : 2 ]) for (b = [0 : 2])  a == b ? 1 : 0 ];
echo(flat_result2); // ECHO: [1, 0, 0, 0, 1, 0, 0, 0, 1]


// nested loop to generate a bi-dimensional matrix
identity_matrix = [ for (a = [ 0 : 2 ]) [ for (b = [ 0 : 2 ]) a == b ? 1 : 0 ] ];
echo(identity_matrix); // ECHO: [[1, 0, 0], [0, 1, 0], [0, 0, 1]]


高階示例

[編輯 | 編輯原始碼]

本章列出了一些高階示例、有用的習慣用法和列表理解語法的用例。

生成多邊形的頂點

[編輯 | 編輯原始碼]
結果

使用列表理解,可以計算引數方程在許多點上的值來近似許多曲線,例如以下橢圓的示例(使用 polygon()

sma = 20;  // semi-minor axis
smb = 30;  // semi-major axis

polygon(
    [ for (a = [0 : 5 : 359]) [ sma * sin(a), smb * cos(a) ] ]
);


扁平化巢狀向量

[編輯 | 編輯原始碼]

列表理解可以在使用者定義的函式中使用,以對向量執行操作或任務。以下是一個扁平化巢狀向量的使用者定義函式。

// input : nested list
// output : list with the outer level nesting removed
function flatten(l) = [ for (a = l) for (b = a) b ] ;

nested_list = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ];
echo(flatten(nested_list)); // ECHO: [1, 2, 3, 4, 5, 6]

對向量進行排序

[編輯 | 編輯原始碼]

即使是複雜的演算法 快速排序 也可以透過 for()、if()、let() 和 遞迴 實現。

// input : list of numbers
// output : sorted list of numbers
function quicksort(arr) = !(len(arr)>0) ? [] : let(
    pivot   = arr[floor(len(arr)/2)],
    lesser  = [ for (y = arr) if (y  < pivot) y ],
    equal   = [ for (y = arr) if (y == pivot) y ],
    greater = [ for (y = arr) if (y  > pivot) y ]
) concat(
    quicksort(lesser), equal, quicksort(greater)
);

// use seed in rands() to get reproducible results
unsorted = [for (a = rands(0, 10, 6, 3)) ceil(a)];
echo(unsorted); // ECHO: [6, 1, 8, 9, 3, 2]
echo(quicksort(unsorted)); // ECHO: [1, 2, 3, 6, 8, 9]

選擇向量的元素

[編輯 | 編輯原始碼]

select() 執行元素的選擇和重新排序,生成一個新的向量。

function select(vector, indices) = [ for (index = indices) vector[index] ];
   
vector1 =   [[0,0],[1,1],[2,2],[3,3],[4,4]];
selector1 = [4,0,3];
vector2 =   select(vector1,selector1);    // [[4, 4], [0, 0], [3, 3]]
vector3 =   select(vector1,[0,2,4,4,2,0]);// [[0, 0], [2, 2], [4, 4],[4, 4], [2, 2], [0, 0]]
// range also works as indices
vector4 =   select(vector1, [4:-1:0]);    // [[4, 4], [3, 3], [2, 2], [1, 1], [0, 0]]

連線兩個向量

[編輯 | 編輯原始碼]

使用索引

function cat(L1, L2) = [for (i=[0:len(L1)+len(L2)-1]) 
                        i < len(L1)? L1[i] : L2[i-len(L1)]] ;

echo(cat([1,2,3],[4,5])); //concatenates two OpenSCAD lists [1,2,3] and [4,5], giving [1, 2, 3, 4, 5]

不使用索引

function cat(L1, L2) = [for(L=[L1, L2], a=L) a];

echo(cat([1,2,3],[4,5])); //concatenates two OpenSCAD lists [1,2,3] and [4,5], giving [1, 2, 3, 4, 5]

其他語言特性

[編輯 | 編輯原始碼]

特殊變數

[編輯 | 編輯原始碼]

特殊變數提供了一種將引數傳遞給模組和函式的備用方法。所有以 '$' 開頭的使用者或 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、$fs 和 $fn 控制用於生成弧線的片段數量。

$fa 是片段的最小角度。即使是巨大的圓形,其片段數量也不會超過 360 除以該數字。預設值為 12(即完整的圓形有 30 個片段)。允許的最小值為 0.01。嘗試設定更低的值會導致警告。

$fs 是片段的最小尺寸。預設值為 2,因此非常小的圓形片段數量少於使用 $fa 指定的數量。允許的最小值為 0.01。嘗試設定更低的值會導致警告。

$fn 是片段數量,通常預設值為 0。當該變數的值大於零時,另外兩個變數會被忽略,並且使用該片段數量渲染完整的圓形。

片段數量越高,消耗的記憶體和 CPU 越多;較大的值會導致許多系統崩潰。根據設計,$fn 值以及 $fa 和 $fs 的相應結果應該保持較小,至少在設計最終確定之前應該保持較小,然後可以增加最終結果的值。**不建議使用超過 128 的 $fn**,或者僅在特定情況下使用,建議使用低於 50 的 $fn 以提高效能。

您也可以使用兩個不同的值來進行預覽和渲染。

     $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

[編輯 | 編輯原始碼]
簡諧運動,20 FPS,100 步
動畫齒輪 17T 和 31T

$t 變數在 "rotate" 和 "translate" 中用於動畫,$t*360 給出完整的迴圈。要開始動畫,請選擇 **視窗\動畫** 並在 "FPS" 和 "步長" 中輸入值。 "時間" 欄位將顯示 $t 的當前值,以小數形式表示。

$t 的值將從 0 重複到(1 - 1/步長)。它永遠不會達到 1,因為這會導致動畫在使用它進行旋轉時出現 "卡頓"——兩個連續的幀將處於相同的角度。

沒有變數來區分動畫執行在第一幀($t=0)和動畫未執行的情況,因此請將 $t=0 設定為模型的靜止位置。

簡諧運動

[edit | edit source]

translate ([0, 0, 10*sin($t*360)])

sphere(2);

在 Z 軸上,球體在 -10 到 +10 之間振盪。

旋轉

[edit | edit source]

rotate ([0, 0, $t*360])

square(5);

在 Z 軸上,方塊繞著一個角旋轉。要繞方塊的中心旋轉,請使用

rotate ([0, 0, $t*360])

square(5, center=true);

部分旋轉

[edit | edit source]

在動畫中,所有部分都在相同時間 $t 內完成一個運動週期,跳回零點,然後重新開始。但是,可以為每個週期指定不同的步數,以在同一動畫中產生不同速度的錯覺。這可以用來動畫化不同尺寸的齧合齒輪。

rotate([0, 0, $t*360/17])

gear(teeth=17);

rotate([0, 0, -$t*360/31])

gear(teeth=31);

圓形軌道

[edit | edit source]

rotate ([0, 0, $t*360])

translate ([10, 0])

square(5, center=true);

無旋轉的圓形軌道

[edit | edit source]

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 為 true。在渲染 (F6) 中,$preview 為 false。

例如,這可以用來在預覽期間減少細節以節省時間,而不會在最終渲染結果中丟失細節。

$fn = $preview ? 12 : 72;
sphere(r = 1);

請注意,渲染模組不會影響 $preview。

render(){
    $fn = $preview ? 12 : 72;
    sphere(r = 1);
}

另一個用途可能是使預覽顯示裝配檢視,而渲染只生成為列印而設計的列印部件。

如果列印部件需要在列印後移除的額外功能,例如懸空孔的支撐,則預覽可以省略這些功能以顯示後處理後的成品。

當從命令列執行 OpenSCAD 時,$preview 只有在使用 OpenCSG 生成 PNG 影像時才為 true。當使用 CGAL 生成 STL、DXF 和 SVG 檔案時,它為 false。它在生成 CSG 和 ECHO 檔案時也為 false。這可能符合或不符合您的預期,但您始終可以使用 -D 選項在命令列上覆蓋它,就像任何其他變數一樣。

Echo 模組

[edit | edit source]

echo() 模組將內容列印到編譯視窗 (也稱為控制檯)。這對除錯程式碼很有用。還可以檢視字串函式 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 輸出不受官方支援,但根據 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() 效果顯示邊

強制生成網格,即使是在預覽模式下也是如此。這在某些情況下很有用,例如當布林運算變得太慢而無法跟蹤時。

Render 也可用於 (通常與凸性一起) 避免/解決預覽偽影。[1] 另請參見 OpenSCAD User Manual/FAQ#Why are some parts (e.g. holes) of the model not rendered correctly?

使用示例: (需要描述)

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 軸上居中。否則,物體將放置在正象限中。預設值為 false。
反轉
布林值。反轉匯入影像的顏色值如何轉換為高度值。這在匯入文字資料檔案時沒有影響。預設值為 false.: 使用此引數產生的幾何體以其頂部在 z = 0 平面上的方式定位。一個厚度為一個單位的薄“足跡”層會自動新增到高度圖下方。:: [注意: 需要 2015.03 版本]
凸性
整數。凸度引數指定與物體相交的光線可能穿透的最大正面數(背面數)。此引數僅用於在 OpenCSG 預覽模式下正確顯示物體,對最終渲染沒有影響。

文字檔案格式

[編輯 | 編輯原始碼]

基於文字的高度圖的格式是數字矩陣,代表特定點的海拔高度。行在 Y 軸方向上對映,列在 X 軸方向上對映,相鄰行和列之間有一個單位的增量。數字必須用空格或製表符分隔。空行和以 # 字元開頭的行將被忽略。

[注意: 需要版本 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);
Input image
輸入影像
Surface output
示例 3a: surface(invert = false)
Surface output inverted
示例 3b: surface (invert = true)
示例 3: 使用 surface() 將 PNG 影像作為高度圖輸入。

示例 4

[注意: 需要版本 2015.03]

// Example 4
surface(file = "BRGY-Grey.png", center = true, invert = false);

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 返回一個列表列表,每個列表列表最多包含 num_returns_per_match 個索引值,用於 match_value 的每個元素。
  • 參見下面的示例 8
  • 如果 num_returns_per_match = 0,則 search 返回一個列表列表,其中包含每個 match_value 元素的所有匹配索引值。
  • 參見下面的示例 6
  • index_col_num(預設值:0)
  • 如上所述,在搜尋列表列表時,search 僅檢視每個子列表的一個索引位置。該索引位置由index_col_num指定。
  • 參見下面的示例 5,瞭解簡單的用法示例。

搜尋用法示例

[編輯 | 編輯原始碼]
請參見 OpenSCAD 附帶的example023.scad,瞭解可渲染的示例。

索引值以列表形式返回

[編輯 | 編輯原始碼]
示例 程式碼 結果

1

search("a","abcdabcd");

[0]

2

search("e","abcdabcd");

[]

3

search("a","abcdabcd",0);

[[0,4]]

4

data=[ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];

search("a", data, num_returns_per_match=0);

[[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

OpenSCAD 版本

[編輯 | 編輯原始碼]

version() 和 version_num() 返回 OpenSCAD 版本號。

  • version() 函式以三個數字的向量形式返回 OpenSCAD 版本,例如 [2011, 9, 23]
  • version_num() 函式以數字形式返回 OpenSCAD 版本,例如 20110923

parent_module(n) 和 $parent_modules

[edit | edit source]

$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"

斷言

[edit | edit source]

[注意: 需要 2019.05 版本]

另見 斷言(軟體開發)

assert 評估邏輯表示式。如果表示式評估為 false,則預覽/渲染的生成將停止,並且透過控制檯報告錯誤條件。報告包含表示式的字串表示形式和 assert 命令中指定的附加字串(可選)。

 assert(condition);
 assert(condition, message);

引數

條件
表示式。要評估的表示式作為斷言的檢查。
訊息
字串。斷言失敗時輸出的可選訊息。

示例

[edit | edit source]

最簡單的示例是簡單的 assert(false);,例如,在一個名為 assert_example1.scad 的檔案中。

cube();
assert(false);
sphere();
  
// ERROR: Assertion 'false' failed in file assert_example1.scad, line 2

此示例幾乎沒有用處,但簡單的 assert(false); 可用於應該無法訪問的程式碼部分。

檢查引數

[edit | edit source]

一個有用的例子是檢查輸入引數的有效性

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

新增訊息

[edit | edit source]

在編寫庫時,在斷言失敗時向用戶輸出更多資訊可能很有用。

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

在函式中使用斷言

[edit | edit source]

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

第 7 章 -- 使用者定義的函式和模組

[edit | edit source]

OpenSCAD 使用者手冊/OpenSCAD 語言使用者可以透過定義自己的 函式模組 來擴充套件語言。這允許將指令碼部分分組以方便地重複使用不同的值。選擇良好的名稱也有助於記錄您的指令碼。

函式 返回值。

模組 執行操作,但不會返回值。

OpenSCAD 在編譯時計算變數的值,而不是在執行時計算。作用域內的最後一個變數賦值適用於該作用域內的所有位置。它也適用於任何內部作用域或其子級。有關更多詳細資訊,請參見 變數的作用域。將它們視為可覆蓋的常量而不是變數可能會有所幫助。

對於函式和模組,OpenSCAD 為每個使用情況複製指令碼的相關部分。每個副本都有自己的作用域,其中包含特定於該例項的變數和表示式的固定值。

函式和模組的名稱區分大小寫,因此 test()TEST() 指的是不同的函式/模組。

範圍

[edit | edit source]

模組和函式可以在模組定義中定義,在那裡它們僅在該模組的作用域內可見。

例如

function parabola(f,x) = ( 1/(4*f) ) * x*x; 
module plotParabola(f,wide,steps=1) {
  function y(x) = parabola(f,x);
  module plot(x,y) {
    translate([x,y])
      circle(1,$fn=12);
  }
  xAxis=[-wide/2:steps:wide/2];
  for (x=xAxis) 
    plot(x, y(x));
}
color("red")  plotParabola(10, 100, 5);
color("blue") plotParabola(4,  60,  2);

函式 y() 和模組 plot() 無法在全域性作用域中呼叫。

函式

[edit | edit source]

函式對值進行操作以計算並返回新值。

函式定義
function name ( parameters ) = value ;
名稱
您為該函式起的名稱。一個有意義的名稱在以後會有所幫助。目前有效的名稱只能由簡單字元和下劃線 [a-zA-Z0-9_] 組成,並且不允許使用高 ASCII 或 Unicode 字元。
引數
零個或多個引數。可以為引數分配預設值,以便在呼叫時省略引數時使用。引數名稱是本地的,不與同名外部變數衝突。
計算值的表示式。此值可以是向量。

函式使用

[edit | edit source]

使用時,函式被視為值,並且本身不以分號 ; 結尾。

// example 1
    
function func0() = 5;
function func1(x=3) = 2*x+1;
function func2() = [1,2,3,4];
function func3(y=7) = (y==7) ? 5 : 2 ;
function func4(p0,p1,p2,p3) = [p0,p1,p2,p3];
    
echo(func0());            // 5
a =   func1();            // 7
b =   func1(5);           // 11
echo(func2());            // [1, 2, 3, 4]
echo(func3(2), func3());  // 2, 5
   
z = func4(func0(), func1(), func2(), func3());
//  [5, 7, [1, 2, 3, 4], 5]
   
translate([0, -4*func0(), 0])
  cube([func0(), 2*func0(), func0()]);
// same as translate([0,-20,0]) cube([5,10,5]);
// example 2  creates for() range to give desired no of steps to cover range
  
function steps(start, no_steps, end) =
  [start : (end-start)/(no_steps-1) : end];
  
echo(steps(10, 3, 5));                // [10 : -2.5 : 5]
for (i = steps(10, 3, 5))  echo(i);   //  10 7.5 5
  
echo(steps(10, 3, 15));               // [10 : 2.5 : 15]
for (i = steps(10, 3, 15)) echo(i);   // 10 12.5 15
  
echo(steps(0, 5, 5));                // [0 : 1.25 : 5]
for (i = steps(0, 5, 5))   echo(i);  // 0 1.25 2.5 3.75 5
示例 3
// example 3     rectangle with top pushed over, keeping same y
  
function rhomboid(x=1, y=1, angle=90)
  = [[0,0],[x,0],
    [x+x*cos(angle)/sin(angle),y],
    [x*cos(angle)/sin(angle),y]];
    
echo (v1); v1 = rhomboid(10,10,35);  // [[0, 0], 
                                     // [10, 0], 
                                     // [24.2815, 10],
                                     // [14.2815, 10]]
polygon(v1);
polygon(rhomboid(10,10,35));         // alternate
//performing the same action with a module
   
module parallelogram(x=1,y=1,angle=90)
    {polygon([[0,0],[x,0],
              [x+x*cos(angle)/sin(angle),y],
              [x*cos(angle)/sin(angle),y]]);};
  
parallelogram(10,10,35);

您還可以使用 let 語句 在函式中建立變數

function get_square_triangle_perimeter(p1, p2) =
  let (hypotenuse = sqrt(p1*p1+p2*p2))
    p1 + p2 + hypotenuse;

它可以用於在遞迴函式中儲存值。有關一般概念的更多資訊,請參見 維基百科頁面

遞迴函式

[edit | edit source]

遞迴 函式呼叫受支援。使用條件運算子 "... ? ... : ... ",可以確保遞迴終止。

// recursion example: add all integers up to n
function add_up_to(n) = ( n==0 ? 0 : n + add_up_to(n-1) );

存在一個內建的遞迴限制,以防止應用程式崩潰(幾千個)。如果達到限制,您會收到類似以下的錯誤:ERROR: Recursion detected calling function ... 。

對於所有 尾遞迴 函式呼叫自身,OpenSCAD 能夠在內部消除遞迴,將其轉換為迭代迴圈。前面的示例程式碼不是尾呼叫,因為“add”操作需要在呼叫後計算。但以下有資格進行尾遞迴消除

// tail-recursion elimination example: add all integers up to n
function add_up_to(n, sum=0) =
    n==0 ?
        sum :
        add_up_to(n-1, sum+n);
 
echo(sum=add_up_to(100000));
// ECHO: sum = 5.00005e+009

尾遞迴消除允許更高的遞迴限制(高達 1000000)。

函式文字

[edit | edit source]

[注意: 需要版本 2021.01]

函式文字 是定義函式的表示式,其他名稱是 lambda 或閉包。

函式文字
function (x) x + x

函式文字可以分配給變數,並像任何值一樣傳遞。呼叫函式使用帶括號的正常函式呼叫語法。

func = function (x) x * x;
echo(func(5)); // ECHO: 25

可以定義返回函式的函式。未繫結的變數由詞法作用域捕獲。

a = 1;
selector = function (which)
             which == "add"
             ? function (x) x + x + a
             : function (x) x * x + a;
             
echo(selector("add"));     // ECHO: function(x) ((x + x) + a)
echo(selector("add")(5));  // ECHO: 11

echo(selector("mul"));     // ECHO: function(x) ((x * x) + a)
echo(selector("mul")(5));  // ECHO: 26

覆蓋內建函式

[edit | edit source]

可以覆蓋內建函式。請注意,定義首先處理,因此評估確實為 echo() 兩個呼叫返回 true,因為這些呼叫在後面的處理步驟中進行評估。

原始碼 控制檯輸出
echo (sin(1));
function sin(x) = true;
echo (sin(1));
Compiling design (CSG Tree generation)...
ECHO: true
ECHO: true
Compiling design (CSG Products generation)...

模組

[edit | edit source]

模組可用於定義物件,或者使用 children() 定義運算子。一旦定義,模組就會暫時新增到語言中。

模組定義
module name ( parameters ) { actions }
名稱
您為該模組起的名稱。嘗試選擇一個有意義的名稱。目前有效的名稱只能由簡單字元和下劃線 [a-zA-Z0-9_] 組成,並且不允許使用高 ASCII 或 Unicode 字元。
引數
零個或多個引數。可以為引數分配預設值,以便在呼叫時省略引數時使用。引數名稱是本地的,不與同名外部變數衝突。
操作
模組外部幾乎所有有效的語句都可以包含在模組中。這包括函式和其他模組的定義。這些函式和模組只能從封閉模組中呼叫。

可以分配變數,但它們的作用域僅限於模組的每次單獨使用。OpenSCAD 中沒有機制讓模組將值返回到外部。有關更多詳細資訊,請參見 變數的作用域

物件模組

[edit | edit source]

物件模組使用一個或多個基元以及相關的運算子來定義新物件。

在使用中,物件模組是使用分號“;”結尾的操作。

name ( parameter values );
顏色條
//example 1
   
translate([-30,-20,0])
   ShowColorBars(Expense);
   
ColorBreak=[[0,""],
           [20,"lime"],  // upper limit of color range
           [40,"greenyellow"],
           [60,"yellow"],
           [75,"LightCoral"],
           [200,"red"]];
Expense=[16,20,25,85,52,63,45];
   
module ColorBar(value,period,range){  // 1 color on 1 bar
   RangeHi = ColorBreak[range][0];
   RangeLo = ColorBreak[range-1][0];
   color( ColorBreak[range][1] ) 
   translate([10*period,0,RangeLo])
      if (value > RangeHi)      cube([5,2,RangeHi-RangeLo]);
      else if (value > RangeLo) cube([5,2,value-RangeLo]);
  }  
module ShowColorBars(values){
    for (month = [0:len(values)-1], range = [1:len(ColorBreak)-1])
      ColorBar(values[month],month,range);
}
房子
//example 2
module house(roof="flat",paint=[1,0,0]) {
   color(paint)
   if(roof=="flat") { translate([0,-1,0]) cube(); }
   else if(roof=="pitched") {
     rotate([90,0,0]) linear_extrude(height=1)
     polygon(points=[[0,0],[0,1],[0.5,1.5],[1,1],[1,0]]); }
   else if(roof=="domical") {
     translate([0,-1,0]){
       translate([0.5,0.5,1]) sphere(r=0.5,$fn=20); cube(); }
} }

                   house();
translate([2,0,0]) house("pitched");
translate([4,0,0]) house("domical",[0,1,0]);
translate([6,0,0]) house(roof="pitched",paint=[0,0,1]);
translate([0,3,0]) house(paint=[0,0,0],roof="pitched");
translate([2,3,0]) house(roof="domical");
translate([4,3,0]) house(paint=[0,0.5,0.5]);
//example 3
   
element_data = [[0,"","",0],  // must be in order
    [1,"Hydrogen","H",1.008],   // indexed via atomic number
    [2,"Helium",  "He",4.003]   // redundant atomic number to preserve your sanity later
];
   
Hydrogen = 1;
Helium   = 2;
      
module coaster(atomic_number){
    element     = element_data[atomic_number][1];
    symbol      = element_data[atomic_number][2];
    atomic_mass = element_data[atomic_number][3];
    //rest of script
}

運算子模組

[edit | edit source]

子項

[edit | edit source]

使用 children() 允許模組充當作用於此模組例項化中任何或所有物件的運算子。在使用中,運算子模組不以分號結尾。

name ( parameter values ){scope of operator}

基本上 children() 命令用於對由範圍聚焦的物件應用修改

 module myModification() { rotate([0,45,0]) children(); } 
 
 myModification()                 // The modification
 {                                // Begin focus
   cylinder(10,4,4);              // First child
   cube([20,2,2], true);          // Second child
 }                                // End focus


物件透過從 0 到 $children-1 的整數索引。OpenSCAD 將 $children 設定為範圍內的物件總數。分組到子範圍內的物件被視為一個子項。 參見下面單獨子項的示例變數範圍。請注意,children()echo() 和空塊語句(包括 ifs)被計為 $children 物件,即使沒有幾何圖形存在(截至 v2017.12.23)。

 children();                         all children
 children(index);                    value or variable to select one child
 children([start : step : end]);     select from start to end incremented by step
 children([start : end]);            step defaults to 1 or -1
 children([vector]);                 selection of several children

已棄用的 child() 模組

在 2013.06 版本之前,使用的是現在已棄用的 child() 模組。這可以根據表格轉換為新的 children()

截至 2013.06 2014.03 及更高版本
child() children(0)
child(x) children(x)
for (a = [0:$children-1]) child(a) children([0:$children-1])
使用所有子項

示例

//Use all children
    
module move(x=0,y=0,z=0,rx=0,ry=0,rz=0)
{ translate([x,y,z])rotate([rx,ry,rz]) children(); }
   
move(10)           cube(10,true);
move(-10)          cube(10,true);
move(z=7.07, ry=45)cube(10,true);
move(z=-7.07,ry=45)cube(10,true);
多次使用第一個子項
//Use only the first child, multiple times
  
module lineup(num, space) {
   for (i = [0 : num-1])
     translate([ space*i, 0, 0 ]) children(0);
}

lineup(5, 65){ sphere(30);cube(35);}
對每個子項進行單獨操作
  //Separate action for each child
   
  module SeparateChildren(space){
    for ( i= [0:1:$children-1])   // step needed in case $children < 2  
      translate([i*space,0,0]) {children(i);text(str(i));}
  }
   
  SeparateChildren(-20){
    cube(5);              // 0
    sphere(5);            // 1
    translate([0,20,0]){  // 2
      cube(5);
      sphere(5);
    }     
    cylinder(15);         // 3
    cube(8,true);         // 4
  }
  translate([0,40,0])color("lightblue")
    SeparateChildren(20){cube(3,true);}
多個範圍
//Multiple ranges
module MultiRange(){
   color("lightblue") children([0:1]);
   color("lightgreen")children([2:$children-2]);
   color("lightpink") children($children-1);
}
   
MultiRange()
{
   cube(5);              // 0
   sphere(5);            // 1
   translate([0,20,0]){  // 2
     cube(5);
     sphere(5);
   }     
   cylinder(15);         // 3
   cube(8,true);         // 4
}

更多模組示例

[edit | edit source]
物件
module arrow(){
    cylinder(10);
    cube([4,.5,3],true);
    cube([.5,4,3],true);
    translate([0,0,10]) cylinder(4,2,0,true);
}
  
module cannon(){
    difference(){union()
      {sphere(10);cylinder(40,10,8);} cylinder(41,4,4);
} }
  
module base(){
    difference(){
      cube([40,30,20],true);
      translate([0,0,5])  cube([50,20,15],true);
} }
運算子
旋轉叢集
module aim(elevation,azimuth=0)
    { rotate([0,0,azimuth])
      { rotate([0,90-elevation,0]) children(0);
      children([1:1:$children-1]);   // step needed in case $children < 2
} }
   
aim(30,20)arrow();
aim(35,270)cannon();
aim(15){cannon();base();}

module RotaryCluster(radius=30,number=8)
    for (azimuth =[0:360/number:359])
      rotate([0,0,azimuth])    
        translate([radius,0,0]) { children();
          translate([40,0,30]) text(str(azimuth)); }
   
RotaryCluster(200,7) color("lightgreen") aim(15){cannon();base();}
rotate([0,0,110]) RotaryCluster(100,4.5) aim(35)cannon();
color("LightBlue")aim(55,30){cannon();base();}

遞迴模組

[edit | edit source]

與函式一樣,模組可能包含遞迴呼叫。但是,遞迴模組沒有尾遞迴消除。

下面的程式碼生成了一個粗糙的樹模型。每個樹枝本身是樹的修改版本,由遞迴產生。注意將遞迴深度(分支)n 保持在 7 以下,因為基元的數量和預覽時間呈指數增長。

用遞迴 OpenSCAD 模組建立的簡單樹
    module simple_tree(size, dna, n) {   
        if (n > 0) {
            // trunk
            cylinder(r1=size/10, r2=size/12, h=size, $fn=24);
            // branches
            translate([0,0,size])
                for(bd = dna) {
                    angx = bd[0];
                    angz = bd[1];
                    scal = bd[2];
                        rotate([angx,0,angz])
                            simple_tree(scal*size, dna, n-1);
                }
        }
        else { // leaves
            color("green")
            scale([1,1,3])
                translate([0,0,size/6]) 
                    rotate([90,0,0]) 
                        cylinder(r=size/6,h=size/10);
        }
    }
    // dna is a list of branching data bd of the tree:
    //      bd[0] - inclination of the branch
    //      bd[1] - Z rotation angle of the branch
    //      bd[2] - relative scale of the branch
    dna = [ [12,  80, 0.85], [55,    0, 0.6], 
            [62, 125, 0.6], [57, -125, 0.6] ];
    simple_tree(50, dna, 5);

另一個遞迴模組的示例可以在 技巧和竅門 中找到

覆蓋內建模組

[edit | edit source]

可以覆蓋內建模組。

一個簡單但無用的例子是

module sphere(){
    square();
}
sphere();

注意,覆蓋後無法呼叫內建的 sphere 模組。

使用這種語言特性的更明智的方法是使用擠壓的二維基元覆蓋三維基元。這允許在預設引數中新增附加內容並新增附加引數。

第 8 章 - 除錯輔助

[edit | edit source]

OpenSCAD 使用者手冊/OpenSCAD 語言

修改符用於更改子節點的外觀或行為。它們在除錯中特別有用,在那裡可以用來突出顯示特定物件,或包含或排除它們進行渲染。

高階概念

[edit | edit source]

OpenSCAD 使用不同的庫來實現功能,這可能會給 F5 預覽行為帶來一些不一致性。傳統的變換(平移、旋轉、縮放、映象和多矩陣)在預覽中使用 OpenGL 執行,而其他更高階的變換(如調整大小)執行 CGAL 操作,表現得像影響基礎物件的 CSG 操作,而不僅僅是變換它。特別是這可能會影響修改符,特別是“#”和“%”,其中高亮可能不會直觀地顯示,例如高亮預調整大小的物件,但高亮後縮放的物件。

注意:修改符觸發的顏色變化僅在“編譯”模式下出現,而在“編譯和渲染(CGAL)”模式下不出現。(參見顏色部分。)

背景修改符

[edit | edit source]

忽略此子樹的正常渲染過程,並以透明灰色繪製它(所有變換仍應用於此樹中的節點)。

由於標記的子樹被完全忽略,因此在使用它時可能會產生意想不到的效果,例如,在 difference() 中使用第一個物件。在這種情況下,此物件將以透明灰色渲染,但不會用作 difference() 的基礎!

用法

 % { ... }

示例

difference() {
	cylinder (h = 12, r=5, center = true, $fn=100);
	// first object to be subtracted
	rotate ([90,0,0]) cylinder (h = 15, r=1, center = true, $fn=100);
	// second object to be subtracted
	%rotate ([0,90,0]) cylinder (h = 15, r=3, center = true, $fn=100);
}

示例輸出

沒有修改符的輸出。
新增修改符的輸出。
渲染的模型。


除錯修改符

[edit | edit source]

照常使用此子樹進行渲染過程,但也以透明粉色繪製它。

用法

 # { ... }

示例

difference() {
	// start objects
	cylinder (h = 12, r=5, center = true, $fn=100);
        // first object to be subtracted
	#rotate ([90,0,0]) cylinder (h = 15, r=1, center = true, $fn=100);
        // second object to be subtracted
	#rotate ([0,90,0]) cylinder (h = 15, r=3, center = true, $fn=100);
}

示例輸出

沒有修改符的輸出。
新增修改符的輸出。


根修改符

[edit | edit source]

忽略設計其餘部分,並使用此子樹作為設計根。

用法

 ! { ... }

示例

difference() {
	cube(10, center = true);
	translate([0, 0, 5]) {
		!rotate([90, 0, 0]) {
			#cylinder(r = 2, h = 20, center = true, $fn = 40);
		}
	}
}

示例輸出

沒有修改符的輸出。
新增修改符的輸出。


如帶有活動根修改符的示例輸出所示,rotate() 被執行,因為它屬於用根修改符標記的子樹的一部分,但 translate() 沒有效果。

停用修改符

[edit | edit source]

簡單地忽略整個子樹。

用法

 * { ... }

示例

difference() {
	cube(10, center = true);
	translate([0, 0, 5]) {
		rotate([0, 90, 0]) {
			cylinder(r = 2, h = 20, center = true, $fn = 40);
		}
		*rotate([90, 0, 0]) {
			#cylinder(r = 2, h = 20, center = true, $fn = 40);
		}
	}
}

示例輸出

沒有修改符的輸出。
新增修改符的輸出。


停用修改符允許您註釋掉一個或多個子樹。與使用通常的行註釋或多行註釋相比,它瞭解層次結構,這使得即使無需搜尋子樹的結尾也能更容易地停用更大的樹。

回顯語句

[edit | edit source]
另請參閱:OpenSCAD 使用者手冊/其他語言功能#Echo 函式

此函式將內容列印到編譯視窗(又稱控制檯)。對除錯程式碼很有用。另請參閱字串函式 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

第 9 章 - 外部庫和程式碼檔案

[edit | edit source]

OpenSCAD 使用者手冊/OpenSCAD 語言

使用和包含

[edit | edit source]

為了在 OpenSCAD 中包含來自外部檔案程式碼,可以使用兩個命令

  • include <檔名> 的作用與在包含檔案中的位置寫入包含檔案的內容相同,並且
  • use <filename> 匯入模組和函式,但不執行任何命令,除了定義。

庫檔案在以下位置搜尋:設計開啟的資料夾、OpenSCAD 安裝的庫資料夾以及 OPENSCADPATH 環境變數指定的資料夾。你可以使用相對路徑指定這兩個位置中的任何一個。如果它們位於其他位置,則必須提供完整路徑。較新的版本具有預定義的使用者庫,請參閱 OpenSCAD_User_Manual/Libraries 頁面,該頁面還記錄了 OpenSCAD 中包含的許多庫檔案。

萬用字元(*,例如 include <MCAD/*.scad>不能用於包含多個檔案。

目錄分隔符

[編輯 | 編輯原始碼]

Windows 和 Linux/Mac 使用不同的目錄分隔符。Windows 使用 \,例如 directory\file.ext,而其他平臺使用 /,例如 directory/file.ext。這可能會導致跨平臺問題。但是,Windows 上的 OpenSCAD 正確處理了 / 的使用,因此在所有 includeuse 語句中使用 / 在所有平臺上都能正常工作。

要訪問父目錄,可以在 Linux 下使用 ../

變數的範圍
[編輯 | 編輯原始碼]

使用 include <filename> 允許在庫中指定預設變數。這些預設值可以在主程式碼中被覆蓋。OpenSCAD 變數在程式生命週期中只有一個值。當有多個賦值時,它將採用最後一個值,但在變數首次建立時賦值。當在庫中賦值時,這會產生影響,因為你後來用於更改預設值的任何變數必須在 include 語句之前賦值。請參閱下面的第二個示例。

覆蓋變數
[編輯 | 編輯原始碼]

可以覆蓋 include 中的預設變數,例如

lib.scad

i=1;
k=3;
module x() {
    echo("hello world");
    echo("i=",i,"j=",j,"k=",k);
}

hello.scad

j=4;
include <lib.scad>
x();
i=5;
x();
k=j;
x();

產生以下內容

ECHO: "hello world"
ECHO: "i=", 5, "j=", 4, "k=", 4
ECHO: "hello world"
ECHO: "i=", 5, "j=", 4, "k=", 4
ECHO: "hello world"
ECHO: "i=", 5, "j=", 4, "k=", 4

但是,將 j=4; 放在 include 之後將失敗,產生

ECHO: "hello world"
ECHO: "i=", 5, "j=", 4, "k=", undef
ECHO: "hello world"
ECHO: "i=", 5, "j=", 4, "k=", undef
ECHO: "hello world"
ECHO: "i=", 5, "j=", 4, "k=", undef

示例 “環形庫”

[編輯 | 編輯原始碼]

用於生成環形的庫檔案可能如下所示(定義函式並提供示例)

ring.scad

module ring(r1, r2, h) {
    difference() {
        cylinder(r = r1, h = h);
        translate([ 0, 0, -1 ]) cylinder(r = r2, h = h+2);
    }
}

ring(5, 4, 10);

使用以下方法包含庫

include <ring.scad>
rotate([90, 0, 0]) ring(10, 1, 1);

將導致顯示示例環形,以及旋轉後的環形,但是

use <ring.scad>
rotate([90, 0, 0]) ring(10, 1, 1);

僅顯示旋轉後的環形。

如果使用 use 函式,請確保將 use 語句放在檔案開頭,或者至少不要放在模組中!

這可以正常工作

 // a.scad
 use <ring.scad>
 module a() {
   ring();
 }

但這會導致語法錯誤

 //a.scad
 module a() {
   use <ring.scad>
   ring();
 }


巢狀 Include 和 Use

[編輯 | 編輯原始碼]

OpenSCAD 執行對 includeuse 的巢狀呼叫。這裡有一個注意事項,即 use 僅將函式和模組引入本地檔案上下文。因此,對 use 的巢狀呼叫不會對基檔案的環境產生任何影響;子 use 呼叫在父 use 上下文中工作,但這樣匯入的模組和函式在基上下文看到它們之前就超出了上下文。

匯入透過 import() 命令實現。

[注意: 需要版本 2015.03-2] 檔案 >> 開啟 命令可用於插入此命令。開啟檔案對話方塊的檔案型別過濾器可能僅顯示 OpenSCAD 檔案,但檔名可以替換為萬用字元(例如 *.stl)以瀏覽其他檔案型別。

匯入檔案以供在當前 OpenSCAD 模型中使用。副檔名用於確定型別。

3D 幾何圖形格式
  • STL(ASCII 和二進位制)
  • OFF
  • OBJ
  • AMF(已棄用)
  • 3MF
2D 幾何圖形格式
資料格式
  • JSON [注意: 需要版本 開發快照]
其他
  • CSG 可以使用 include<> 匯入,也可以像 SCAD 檔案一樣載入
  • PNG 可以使用 surface() 匯入
<file>
包含檔案路徑的字串:如果給定的路徑不是絕對路徑,則將其解析為相對於匯入指令碼的路徑。請注意,當使用 include<> 與使用 import() 的指令碼一起使用時,它是相對於執行 include<> 的指令碼的路徑。
<convexity>
整數。convexity 引數指定與物件相交的光線可能穿透的最大正面數量(或背面數量)。此引數僅在 OpenCSG 預覽模式下正確顯示物件時需要,對多面體渲染沒有影響。可選。
<id>
字串。僅限於 SVG 匯入,要匯入的元素或組的 ID。可選。 [注意: 需要版本 開發快照]
<layer>
僅限於 DXF 和 SVG 匯入,指定要匯入的特定圖層。可選。
$fn
雙精度浮點數。將圓形、弧線和曲線轉換為多邊形時要使用的多邊形段數。 [注意: 需要版本 開發快照]
$fa
雙精度浮點數。將圓形和弧線轉換為多邊形時要使用的最小角度步長。 [注意: 需要版本 開發快照]
$fs
雙精度浮點數。將圓形和弧線轉換為多邊形時要使用的最小線段長度。 [注意: 需要版本 開發快照]
import("example012.stl", convexity=3);
import("D:/Documents and Settings/User/My Documents/Gear.stl", convexity=3);
(Windows users must "escape" the backslashes by writing them doubled, or replace the backslashes with forward slashes.)
data = import("data.json"); // for data formats the file content is assigned to a variable

讀取 2D DXF 檔案的圖層並建立 3D 形狀。

linear_extrude(height = 5, center = true, convexity = 10)
		import_dxf(file = "example009.dxf", layer = "plate");

此影像顯示了一個凸度為 2 的 2D 形狀,因為用紅色指示的光線最多與 2D 形狀相交兩次。3D 形狀的凸度將以類似的方式確定。將其設定為 10 對於大多數情況應該可以正常工作。

在最新版本的 OpenSCAD 中,import() 現在用於匯入 2D(用於擠出的 DXF)和 3D(STL)檔案。

CGAL 錯誤:斷言違反!

[編輯 | 編輯原始碼]

如果你想稍後渲染匯入的 STL 檔案,則必須確保 STL 檔案是“乾淨”的。這意味著網格必須是流形,並且不應包含孔或自相交。如果 STL 不乾淨,它可能最初匯入並預覽正常,但只要你嘗試透過將其與其他內容結合渲染來對它執行計算幾何,你可能會收到有關它不是流形的警告,你匯入的 stl 可能會完全從輸出中消失,或者你可能會收到類似的錯誤

 CGAL error in CGAL_Build_PolySet: CGAL ERROR: assertion violation!
 Expr: check_protocoll == 0
 File: /home/don/openscad_deps/mxe/usr/i686-pc-mingw32/include/CGAL/Polyhedron_incremental_builder_3.h
 Line: 199

 CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion violation!
 Expr: pe_prev->is_border() || !internal::Plane_constructor<Plane>::get_plane(pe_prev->facet(),pe_prev->facet()->plane()).is_degenerate()
 File: /home/don/openscad_deps/mxe/usr/i686-pc-mingw32/include/CGAL/Nef_3/polyhedron_3_to_nef_3.h
 Line: 253

為了清理 STL 檔案,你有以下選擇

使用 MeshLab,你可以執行以下操作

  • 渲染 - 顯示非流形邊
  • 渲染 - 顯示非流形頂點
  • 如果發現,請使用過濾器 - 選擇 - 選擇非流形邊或選擇非流形頂點 - 應用 - 關閉。然後單擊按鈕“刪除當前選定的頂點集...”或檢視 http://www.youtube.com/watch?v=oDx0Tgy0UHo 獲取說明影片。螢幕應顯示“0 個非流形邊”、“0 個非流形頂點”。


接下來,你可以單擊“填充孔”圖示,選擇所有孔,然後單擊“填充”,然後單擊“接受”。你可能需要重複此操作幾次。

使用檔案 - 匯出網格儲存 STL。


如果 Meshlab 無法填充最後一個孔,則 Blender 可能會有所幫助

  1. 啟動 Blender
  2. `X, 1` 用於移除預設物件
  3. 檔案, 匯入, Stl
  4. `Tab` 用於編輯網格
  5. `A` 用於取消選擇所有頂點
  6. `Alt+Ctrl+Shift+M` 用於選擇所有非流形頂點
  7. `MMB` 用於旋轉, `Shift+MMB` 用於平移, `滾輪` 用於縮放
  8. `C` 用於“圓形”選擇, `Esc` 用於結束
  9. `Alt+M, 1` 用於合併, 或者使用 `空格` 並搜尋 "merge" 作為替代方案
  10. 合併頂點是填充孔洞的一種有用方法, 在這種情況下, 頂點非常緊密地堆積在一起, 以至於幾何形狀的微小變化與典型 3D 印表機的精度相比微不足道

匯入 JSON

[編輯 | 編輯原始碼]

這需要在開發版本中啟用 import-function 功能。如果您匯入一個字尾為 "json" 或 "csv" 的檔案, 匯入將返回一個 JSON 物件資料型別, 該型別無法以字面值表示 - 它只能被匯入。

注意: 字尾為 ".csv" 的檔案也會被視為 JSON 檔案, 儘管這些格式並不相同 - 從電子表格程式儲存的 CSV 檔案不能在這裡使用。

/* input file contains:

{"people":[{"name":"Helen", "age":19}, {"name":"Chris", "age":32}]}
*/
t = import("people.json");
echo(t);
people = t.people;
for(i=[0:len(people)-1]) {
	person = people[i];
	echo(str(person.name, ": ", person.age));
}

這將導致以下輸出

ECHO: { people = [{ age = 19; name = "Helen"; }, { age = 32; name = "Chris"; }]; }
ECHO: "Helen: 19"
ECHO: "Chris: 32"

import_dxf

[編輯 | 編輯原始碼]

[已棄用: import_dxf() 將在未來的版本中移除。請使用 import() 代替。]

讀取 DXF 檔案並建立一個 3D 形狀。

linear_extrude(height = 5, center = true, convexity = 10)
		import_dxf(file = "example009.dxf", layer = "plate");

import_stl

[編輯 | 編輯原始碼]

[已棄用: import_stl() 將在未來的版本中移除。請使用 import() 代替。見上文。]

匯入 STL 檔案以供在當前 OpenSCAD 模型中使用

import_stl("body.stl", convexity = 5);

surface() 從文字或影像檔案讀取 高度圖 資訊。它可以讀取 PNG 檔案。

檔案
字串。包含高度圖資料的檔案的路徑。
中心
布林值。這決定了生成的物體的定位。如果為真,則物體在 X 軸和 Y 軸上居中。否則,物體將放置在正象限中。預設值為 false。
反轉
布林值。反轉匯入影像的顏色值如何轉換為高度值。這在匯入文字資料檔案時沒有影響。預設值為 false。 [注意: 需要版本 2015.03]
凸性
整數。凸度引數指定與物件相交的射線可能穿透的最大正面(背面)數量。此引數僅在 OpenCSG 預覽模式下正確顯示物件時需要,對最終渲染沒有影響。

文字檔案格式

[編輯 | 編輯原始碼]

基於文字的高度圖的格式是表示特定點的高度值的數字矩陣。行對映到 Y 軸,列對映到 X 軸。數字必須用空格或製表符分隔。空行和以 # 字元開頭的行將被忽略。

[注意: 需要版本 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:
 // d = (sin(1:0.2:10)' * cos(1:0.2:10)) * 10;
 // save("example010.dat", "d");
 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);
Input image
輸入影像
Surface output
示例 3a: surface(invert = false)
Surface output inverted
示例 3b: surface(invert = true)
示例 3: 使用 surface() 將 PNG 影像作為高度圖輸入。
  1. https://github.com/openscad/openscad/issues/4275
華夏公益教科書