跳轉到內容

OpenSCAD 教程/第 2 章

來自華夏公益教科書

縮放部件或整個模型

[編輯 | 編輯原始碼]

您在上章建立的模型是使用 OpenSCAD 的一個很好的起點,但也許在看到它之後,您會發現一些應該更改的方面。在這裡,我們將討論修改設計元件的策略。一種方法是使用 scale 命令,它是另一個轉換命令。修改建立汽車車身底部的語句,如下所示,以便將車身的長度按 1.2 的比例增加。

程式碼

car_with_lengthened_body_base.scad

…
// Car body base
scale([1.2,1,1])
    cube([60,20,10],center=true);
…

您應該注意到,scale 命令的使用方式與 transform 和 rotate 命令類似。它被新增到現有語句的左側,語句之間不包含分號,並且它有一個作為輸入引數的三值向量。與 translate 和 rotate 命令類似,每個值對應於沿 X、Y 和 Z 軸的縮放比例。

練習
嘗試修改 scale 命令的輸入,以便沿 X 軸將車身底部按 1.2 的比例縮放,沿 Y 軸按 0.1 或 2 的比例縮放。您是否獲得了可以作為火星車或坦克的東西?您是否對這些模型與原始汽車相比的外觀差異感到驚訝?

也可以將相同的 scale 命令或任何其他變換命令應用於多個物件。使用以下程式碼將 scale 命令應用於汽車車身的底部和頂部。

程式碼

car_with_lengthened_body.scad

scale([1.2,1,1]) {
    // Car body base
    cube([60,20,10],center=true);
    // Car body top
    translate([5,0,10 - 0.001])
        cube([30,20,10],center=true);
}

您應該注意的第一件事是,為了將 scale 命令應用於多個物件,使用了花括號。定義相應物件以及它們的分號的語句都放在花括號內。花括號在末尾不需要分號。

您應該注意的第二件事是,空格和註釋的使用如何提高指令碼的可讀性。以下指令碼完全相同,您可以自行決定想閱讀哪一個。

程式碼
scale([1.2,1,1]) {
    cube([60,20,10],center=true);
    translate([5,0,10 - 0.001])
        cube([30,20,10],center=true);
}
練習
嘗試將 scale 命令應用於您的整個模型。您是否記得將所有語句都包含在花括號內?為了使車輪不發生變形,沿 X 和 Z 軸的縮放因子之間應該是什麼關係?為了獲得比例相同但尺寸加倍的汽車,縮放因子應該是什麼?
  • 為了使車輪不發生變形,沿 X 和 Z 軸的縮放因子應該相等。
程式碼

scaled_car.scad

$fa = 1;
$fs = 0.4;
scale([2,2,2]) {
    // Car body base
    cube([60,20,10],center=true);
    // Car body top
    translate([5,0,10 - 0.001])
        cube([30,20,10],center=true);
    // Front left wheel
    translate([-20,-15,0])
        rotate([90,0,0])
        cylinder(h=3,r=8,center=true);
    // Front right wheel
    translate([-20,15,0])
        rotate([90,0,0])
        cylinder(h=3,r=8,center=true);
    // Rear left wheel
    translate([20,-15,0])
        rotate([90,0,0])
        cylinder(h=3,r=8,center=true);
    // Rear right wheel
    translate([20,15,0])
        rotate([90,0,0])
        cylinder(h=3,r=8,center=true);
    // Front axle
    translate([-20,0,0])
        rotate([90,0,0])
        cylinder(h=30,r=2,center=true);
    // Rear axle
    translate([20,0,0])
        rotate([90,0,0])
        cylinder(h=30,r=2,center=true);
}

快速測驗

[編輯 | 編輯原始碼]

以下指令碼是您在第一章中建立的模型。

程式碼
$fa = 1;
$fs = 0.4;
// Car body base
cube([60,20,10],center=true);
// Car body top
translate([5,0,10 - 0.001])
    cube([30,20,10],center=true);
// Front left wheel
translate([-20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=8,center=true);
// Front right wheel
translate([-20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=8,center=true);
// Rear left wheel
translate([20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=8,center=true);
// Rear right wheel
translate([20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=8,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);
練習
嘗試將前輪繞 Z 軸旋轉 20 度,就像汽車正在右轉一樣。為了使您的模型更逼真,嘗試將汽車車身(底部和頂部)繞 X 軸旋轉 5 度,方向與轉向相反。要轉動車輪,請修改現有 rotate 命令的輸入引數,要轉動車身,請新增新的 rotate 命令。
程式碼

turning_car.scad

$fa = 1;
$fs = 0.4;
rotate([5,0,0]) {
    // Car body base
    cube([60,20,10],center=true);
    // Car body top
    translate([5,0,10 - 0.001])
        cube([30,20,10],center=true);
}
// Front left wheel
translate([-20,-15,0])
    rotate([90,0,-20])
    cylinder(h=3,r=8,center=true);
// Front right wheel
translate([-20,15,0])
    rotate([90,0,-20])
    cylinder(h=3,r=8,center=true);
// Rear left wheel
translate([20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=8,center=true);
// Rear right wheel
translate([20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=8,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);

對模型的各個部分進行引數化

[編輯 | 編輯原始碼]

您應該已經瞭解到,模型大多數情況下並非旨在以一種版本存在。OpenSCAD 指令碼語言的強大之處之一在於,它可以輕鬆地重複使用模型,或者只是在您對最終版本感到滿意之前,對模型進行反覆玩弄。現在該對您的汽車進行一些修改了!

練習
嘗試將車輪的半徑更改為 10 個單位。您是否很容易找到要修改的值?您是否必須重複執行四次相同的操作?
程式碼

car_with_larger_wheels.scad

// Front left wheel
translate([-20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=10,center=true);
// Front right wheel
translate([-20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=10,center=true);
// Rear left wheel
translate([20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=10,center=true);
// Rear right wheel
translate([20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=10,center=true);

雖然更改車輪尺寸並不難,但它本來可以更簡單。首先,它本來可以更容易找到要更改的值。其次,您只需要更改一個值,因為所有車輪的半徑都相同。所有這些都可以透過使用變數來實現。在下面的指令碼中,引入了用於定義車輪半徑的變數。

程式碼
wheel_radius = 8;
// Front left wheel
translate([-20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front right wheel
translate([-20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear left wheel
translate([20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear right wheel
translate([20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);

每個變數都有兩個部分:名稱和值。在本例中,變數名稱為“wheel_radius”。有效的變數名只使用字母數字字元和下劃線 (A-Z、a-z、0-9 和 _)。在變數名之後,等於號將名稱與值隔開,然後是值本身。最後,在末尾需要一個分號來表示該語句的完成。最好將變數集中定義在文件的開頭。

定義變數後,可以在程式碼中使用它來表示其值。在本例中,cylinder 命令已修改為使用 wheel_radius 變數作為輸入引數 r。當 OpenSCAD 評估此指令碼時,它將設定輸入引數 r 等於 wheel_radius 變數的值。

練習
嘗試使用名為 wheel_radius 的變數來定義汽車車輪的尺寸。嘗試透過修改 wheel_radius 變數的值來更改車輪尺寸幾次。您是否發現使用 wheel_radius 變數更改車輪尺寸更容易了多少?
程式碼

car_with_smaller_wheels.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 6;
// Car body base
cube([60,20,10],center=true);
// Car body top
translate([5,0,10 - 0.001])
    cube([30,20,10],center=true);
// Front left wheel
translate([-20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front right wheel
translate([-20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear left wheel
translate([20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear right wheel
translate([20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);

有一件重要的事情您應該牢記 OpenSCAD 中變數的行為。OpenSCAD 中的變數的行為類似於常量。它們只能儲存一個值,並且在建立模型的過程中始終保留這個值。那麼,如果在指令碼開頭為 wheel_radius 賦值,然後在定義兩個前輪之後為它賦值,會發生什麼?後輪的尺寸是否會與前輪不同?

練習
嘗試在定義前輪之後立即為 wheel_radius 變數賦值。您的汽車的前後輪尺寸是否不同?
程式碼

car_with_same_sized_wheels.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 6;
// Car body base
cube([60,20,10],center=true);
// Car body top
translate([5,0,10 - 0.001])
    cube([30,20,10],center=true);
// Front left wheel
translate([-20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front right wheel
translate([-20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
wheel_radius = 12;
// Rear left wheel
translate([20,-15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear right wheel
translate([20,15,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=30,r=2,center=true);

您應該注意到,所有車輪的尺寸都相同。如果存在對變數的多次賦值,OpenSCAD 將使用最後一次賦值的值。即使在最後一次賦值之前定義了使用此變數的語句,它們也將使用最後一次賦值的值。


在這種情況下,OpenSCAD 還會發出警告:警告:wheel_radius 在第 3 行被賦值,但在第 17 行被覆蓋

注意
在 { 花括號 } 內的變數賦值僅適用於這些括號內。在不同級別的括號包圍下重複賦值不被視為衝突。

對模型的更多部分進行引數化

[編輯 | 編輯原始碼]

您現在可以輕鬆地玩弄車輪的尺寸。如果您可以用同樣的輕鬆方式自定義模型的更多方面,那就太好了。您應該注意,修改車輪的尺寸不會影響模型的任何其他方面,不會以任何方式破壞您的模型。但並非總是如此。

練習
嘗試透過定義 base_height 和 top_height 變數,並對定義底部和頂部的相應語句進行適當更改,來修改汽車車身底部和頂部的尺寸。將 base_height 變數的值設定為 5,將 top_height 變數的值設定為 8。您發現了什麼?
程式碼

car_with_floating_body_top.scad

base_height = 5;
top_height = 8;
// Car body base
cube([60,20,base_height],center=true);
// Car body top
translate([5,0,10 - 0.001])
    cube([30,20,top_height],center=true);

很明顯,當底座和頂部分離時,汽車的車身不再是一個整體。這是因為車身頂部的正確位置取決於車身底座的高度和車身頂部的的高度。請記住,為了使頂部位於底座的頂部,您需要將頂部沿著 Z 軸平移一個距離,該距離等於底座高度的一半加上頂部高度的一半。如果您想將底座和頂部的的高度引數化,那麼您也應該將頂部沿著 Z 軸的平移引數化。

練習
嘗試使用 `base_height` 和 `top_height` 變數將車身頂部的 Z 軸平移引數化,使其位於車身底座的頂部。嘗試為 `base_height` 和 `top_height` 變數分配不同的值。車身頂部的 位置是否保持正確?
程式碼

car_with_properly_attached_body_top.scad

base_height = 5;
top_height = 8;
wheel_radius = 8;
// Car body base
cube([60,20,base_height],center=true);
// Car body top
translate([5,0,base_height/2+top_height/2 - 0.001])
    cube([30,20,top_height],center=true);

程式碼

car_with_higher_body.scad

base_height = 8;
top_height = 14;

您應該記住,每次引數化模型的某個方面時,您也應該引數化其他依賴的方面,以防止模型分解。

練習
嘗試使用名為 `track` 的新變數引數化軌道(左右車輪之間的距離)。嘗試為 `track` 變數分配不同的值。您觀察到什麼?您的模型的任何其他方面是否依賴於 `track` 變數的值?如果是,請使用 `track` 變數對它進行引數化,以使您的模型不會分解。
程式碼

car_with_unattached_wheels.scad

track = 40;
// Front left wheel
translate([-20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front right wheel
translate([-20,track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear left wheel
translate([20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear right wheel
translate([20,track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);

程式碼

car_with_properly_attached_wheels.scad

track = 40;
// Front left wheel
translate([-20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front right wheel
translate([-20,track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear left wheel
translate([20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear right wheel
translate([20,track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=track,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=track,r=2,center=true);

挑戰

[edit | edit source]

以下指令碼對應於引數化了輪子半徑、底座高度、頂部高度和軌道的汽車模型。

程式碼

car_from_parameterized_script.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 8;
base_height = 10;
top_height = 10;
track = 30;
// Car body base
cube([60,20,base_height],center=true);
// Car body top
translate([5,0,base_height/2+top_height/2 - 0.001])
    cube([30,20,top_height],center=true);
// Front left wheel
translate([-20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front right wheel
translate([-20,track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear left wheel
translate([20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Rear right wheel
translate([20,track/2,0])
    rotate([90,0,0])
    cylinder(h=3,r=wheel_radius,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=track,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=track,r=2,center=true);

練習
嘗試使用 `wheel_width` 變數引數化車輪的寬度,使用 `wheels_turn` 變數引數化前輪繞 Z 軸的旋轉,以及使用 `body_roll` 變數引數化車身繞 X 軸的旋轉。嘗試為 `wheel_radius`、`base_height`、`top_height`、`track`、`wheel_width`、`wheels_turn` 和 `body_roll` 分配不同的值,以建立您喜歡的汽車版本。
程式碼

turning_car_from_parameterized_script.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 10;
base_height = 10;
top_height = 14;
track = 40;
wheel_width = 10;
body_roll = -5;
wheels_turn = 20;
rotate([body_roll,0,0]) {
    // Car body base
    cube([60,20,base_height],center=true);
    // Car body top
    translate([5,0,base_height/2+top_height/2 - 0.001])
        cube([30,20,top_height],center=true);
}
// Front left wheel
translate([-20,-track/2,0])
    rotate([90,0,wheels_turn])
    cylinder(h=wheel_width,r=wheel_radius,center=true);
// Front right wheel
translate([-20,track/2,0])
    rotate([90,0,wheels_turn])
    cylinder(h=wheel_width,r=wheel_radius,center=true);
// Rear left wheel
translate([20,-track/2,0])
    rotate([90,0,0])
    cylinder(h=wheel_width,r=wheel_radius,center=true);
// Rear right wheel
translate([20,track/2,0])
    rotate([90,0,0])
    cylinder(h=wheel_width,r=wheel_radius,center=true);
// Front axle
translate([-20,0,0])
    rotate([90,0,0])
    cylinder(h=track,r=2,center=true);
// Rear axle
translate([20,0,0])
    rotate([90,0,0])
    cylinder(h=track,r=2,center=true);

現在您應該清楚地瞭解到,引數化您的模型可以釋放出重用、自定義和迭代您的設計的能力,以及毫不費力地探索不同可能性。

引數化您自己的模型

[edit | edit source]

您是否已經將新技能應用到實際操作中?您是否自己建立了其他模型?

練習
嘗試引數化您建立的模型的一些或更多方面。看看您可以走多遠!嘗試為定義的變數分配各種組合的值。看看您的設計版本可以有多麼不同。
華夏公益教科書