跳轉到內容

OpenSCAD 使用者手冊/變換

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

基本概念

[編輯 | 編輯原始碼]

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

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);

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

高階概念

[編輯 | 編輯原始碼]

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

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

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

調整大小

[編輯 | 編輯原始碼]

修改子物件的尺寸以匹配給定的 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 軸旋轉。這在 2D 上下文中很有用,因為 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 - 一個包含 4 個元素的 3 個行向量的向量,或一個 4×4 矩陣,其中第 4 行始終強制為 [0,0,0,1]。

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

以下是您可以使用矩陣中獨立元素(前三行)進行的操作的細分。

X 方向縮放Y 方向剪下 XZ 方向剪下 XX 方向平移
X 方向剪下 YY 方向縮放Z 方向剪下 YY 方向平移
X 方向剪下 ZY 方向剪下 ZZ 方向縮放Z 方向平移

第 4 行強制為 [0,0,0,1] 並且可以省略,除非您在傳遞給 multmatrix 之前組合矩陣,因為它不會在 OpenSCAD 中處理。每個矩陣都對給定幾何圖形的點進行操作,就好像每個頂點都是一個包含 4 個元素的向量,由一個 3D 向量組成,其中隱式地將 1 作為其第 4 個元素,例如 v=[x, y, z, 1]。m 的隱式第四行的作用是保留向量第 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),它現在已旋轉,並且正在使立方體沿半徑為 v 的圓形路徑繞 z 軸移動,而不會旋轉立方體。

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 顏色列表。顏色名稱圖表如下所示,
(注意,灰色/灰色的兩種拼寫,包括深石板灰/深石板灰等,都是有效的):

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

這是一個繪製波浪狀多色物件的程式碼片段。

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

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

[注意: 需要版本 2015.03]

偏移操作從現有輪廓生成新的二維內部或外部輪廓。它有兩種操作模式:徑向和增量。

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

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

偏移操作對於建立薄壁很有用,方法是從原始輪廓中減去負偏移構造,或從正偏移構造中減去原始輪廓。

偏移操作可用於模擬一些常見的實體建模操作。

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

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

rdelta

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

$fa$fs$fn

可以使用 圓形解析度 特殊變數來控制徑向偏移生成的曲線的平滑度或面尺寸。它們對增量偏移沒有影響。
正 r/增量值
負 r/增量值
不同引數的結果。黑色多邊形是 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();
     }
   }
}


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

填充操作會從多邊形中刪除孔,而不改變輪廓。對於凸多邊形,結果與 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);
}

注意:第二個物件的原點用於加法。以下閔可夫斯基和是不同的:第一個從圓柱體向 -x、+x、-y、+y 方向擴充套件原始立方體 +1 個單位,從圓柱體向 -z、+z 方向擴充套件 0.5 個單位。第二個從圓柱體向 -x、+x、-y、+y 和 +z 方向擴充套件它 +1 個單位,但從圓柱體向 -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);
}

二維物件的凸包使用它們在 xy 平面上的投影(陰影),並在 xy 平面生成結果。它們的高度不會在操作中使用。

參考兩個圓柱體的凸包的插圖,在兩個二維圓上使用 hull() 然後 線性拉伸 生成的二維形狀以形成三維形狀在計算上更有效,而不是在兩個圓柱體上使用 hull(),即使結果物件看起來相同。如果可能,透過從二維開始,可以更快地渲染涉及 hull() 的複雜幾何形狀。

華夏公益教科書