跳轉到內容

OpenSCAD 教程/第 3 章

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

球體基元和調整物件大小

[編輯 | 編輯原始碼]

你向朋友展示了你的汽車,他們對你新掌握的技能印象深刻。其中一人甚至挑戰你設計不同的未來派車輪。現在是發揮你的創造力並學習更多 OpenSCAD 功能的時候了!

到目前為止,你一直在使用立方體和圓柱體基元。OpenSCAD 中可用的另一個 3D 基元是球體。你可以使用以下命令建立球體。

程式碼

sphere.scad

sphere(r=10);

你應該注意到球體是以原點為中心建立的。輸入引數 r 對應於球體的半徑。

你突然想到一個想法,用球形車輪替換圓柱形車輪。

練習
嘗試將你汽車的車輪做成球形。為此,將相應的圓柱體命令替換為球體命令。是否仍然需要繞 X 軸旋轉車輪?wheel_width 變數是否仍然需要?當你修改 wheels_turn 變數的值時,你的模型是否有任何可見的變化?
程式碼

car_with_spherical_wheels.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 8;
base_height = 8;
top_height = 10;
track = 40;
body_roll = 0;
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([0,0,wheels_turn])
    sphere(r=wheel_radius);
// Front right wheel
translate([-20,track/2,0])
    rotate([0,0,wheels_turn])
    sphere(r=wheel_radius);
// Rear left wheel
translate([20,-track/2,0])
    rotate([0,0,0])
    sphere(r=wheel_radius);
// Rear right wheel
translate([20,track/2,0])
    rotate([0,0,0])
    sphere(r=wheel_radius);
// 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);

使用球體來建立車輪的想法很好。你現在可以壓縮球體,使其更像車輪形狀。一種方法是使用 scale 命令。

練習
嘗試在一個空白模型上建立一個半徑為 10 個單位的球體。使用 scale 命令將球體沿著 Y 軸按 0.4 的比例縮放。
程式碼

narrowed_spherical_wheel_using_scale.scad

scale([1,0.4,1])
    sphere(r=10);

另一種縮放物件的方法是使用 resize 變換。scale 和 resize 之間的區別在於,使用 scale 命令時,你必須指定每個軸上所需的縮放因子,而使用 resize 命令時,你必須指定每個軸上物件所需的最終尺寸。在前面的示例中,你從一個半徑為 10 個單位(每個軸上的總尺寸為 20 個單位)的球體開始,並將其沿著 Y 軸按 0.4 的比例縮放。因此,縮放後的球體沿著 Y 軸的最終尺寸為 8 個單位。沿著 X 和 Z 軸的尺寸保持不變(20 個單位),因為這些軸上的縮放因子等於 1。你可以使用以下 resize 命令實現相同的結果。

程式碼

narrowed_spherical_wheel_using_resize.scad

resize([20,8,20])
    sphere(r=10);

當你縮放/調整物件大小並且關心它的最終尺寸時,使用 resize 命令更方便。相反,當你更關心最終尺寸相對於起始尺寸的比例時,使用 scale 命令更方便。

練習
嘗試將你汽車的球形車輪沿著 Y 軸壓縮。使用 resize 命令和 wheel_width 變數來控制車輪的最終寬度。僅沿著 Y 軸調整車輪大小。
程式碼

car_with_narrowed_spherical_wheels.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 8;
base_height = 8;
top_height = 10;
track = 30;
wheel_width = 4;
body_roll = 0;
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([0,0,wheels_turn])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// Front right wheel
translate([-20,track/2,0])
    rotate([0,0,wheels_turn])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// Rear left wheel
translate([20,-track/2,0])
    rotate([0,0,0])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// Rear right wheel
translate([20,track/2,0])
    rotate([0,0,0])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// 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);

新的車輪設計看起來很酷。你現在可以建立一個更適合這種新風格的車身。

練習
嘗試使用 sphere 和 resize/scale 命令代替 cube 命令來建立一個與車輪風格相匹配的車身。
程式碼

car_with_narrowed_spherical_wheels_and_body.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 8;
base_height = 8;
top_height = 10;
track = 28;
wheel_width = 4;
body_roll = 0;
wheels_turn = -20;
rotate([body_roll,0,0]) {
    // Car body base
    resize([90,20,12])
        sphere(r=10);
    // Car body top
    translate([10,0,5])
        resize([50,15,15])
        sphere(r=10);
}
// Front left wheel
translate([-20,-track/2,0])
    rotate([0,0,wheels_turn])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// Front right wheel
translate([-20,track/2,0])
    rotate([0,0,wheels_turn])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// Rear left wheel
translate([20,-track/2,0])
    rotate([0,0,0])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// Rear right wheel
translate([20,track/2,0])
    rotate([0,0,0])
    resize([2*wheel_radius,wheel_width,2*wheel_radius])
    sphere(r=wheel_radius);
// 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);

以其他方式組合物件

[編輯 | 編輯原始碼]

到目前為止,當你想要在你的模型中建立一個額外的物件時,你只需在你的指令碼中新增另一個語句。最終的汽車模型是你指令碼中定義的所有物件的並集。你一直在隱式地使用 union 命令,它是可用的布林運算之一。使用 union 布林運算時,OpenSCAD 會將所有物件的並集作為最終模型。在以下指令碼中,union 被隱式地使用。

程式碼

union_of_two_spheres_implicit.scad

sphere(r=10);
translate([10,0,0])
    sphere(r=10);

你可以透過在你的指令碼中包含 union 命令來明確使用 union。

程式碼

union_of_two_spheres_explicit.scad

union() {
    sphere(r=10);
    translate([12,0,0])
        sphere(r=10);
}

你應該注意到 union 命令沒有任何輸入引數。這對所有布林運算都是如此。union 應用於花括號內的所有物件。你應該還注意到花括號內的語句末尾有一個分號。相反,在結束的花括號後面沒有分號。此語法類似於將變換應用於多個物件時的用法。

總共有三種布林運算。第二種是 difference。difference 命令從第一個物件中減去第二個物件和花括號內定義的所有後續物件。當使用 difference 運算而不是 union 時,前面的示例會產生以下模型。

程式碼

difference_of_two_spheres.scad

difference() {
    sphere(r=10);
    translate([12,0,0])
        sphere(r=10);
}

進一步定義的物件(第三個、第四個等)也會被減去。以下示例有三個物件。

程式碼

difference_of_three_spheres.scad

difference() {
    sphere(r=10);
    translate([12,0,0])
        sphere(r=10);
    translate([0,-12,0])
        sphere(r=10);
}

第三個布林運算子是 intersection。intersection 運算僅保留所有物件的重疊部分。當使用 intersection 運算時,前面的示例會產生以下模型。

程式碼

intersection_of_three_spheres.scad

intersection() {
    sphere(r=10);
    translate([12,0,0])
        sphere(r=10);
    translate([0,-12,0])
        sphere(r=10);
}

最終模型是所有三個物件的公共區域。

當僅在花括號內定義前兩個球體時,intersection 如下所示。

程式碼

intersection_of_two_spheres.scad

intersection() {
    sphere(r=10);
    translate([12,0,0])
        sphere(r=10);
}

練習
嘗試使用 difference 運算來建立一個新的車輪設計。為此,首先建立一個球體,然後從兩側減去一部分球體。第一個球體的半徑應等於所需的車輪半徑(wheel_radius 變數)。另外兩個球體的半徑應等於 side_spheres_radius 變數。給定 hub_thickness 變數,另外兩個球體沿著 Y 軸的正方向和負方向應該平移多少個單位,以便第一個球體中心的剩餘材料的厚度等於 hub_thickness 的值?
程式碼

wheel_with_spherical_sides.scad

$fa = 1;
$fs = 0.4;
wheel_radius=10;
side_spheres_radius=50;
hub_thickness=4;
difference() {
    sphere(r=wheel_radius);
    translate([0,side_spheres_radius + hub_thickness/2,0])
        sphere(r=side_spheres_radius);
    translate([0,- (side_spheres_radius + hub_thickness/2),0])
        sphere(r=side_spheres_radius);
}

練習
嘗試透過減去四個垂直於車輪的圓柱體來從車輪中移除一些材料。圓柱體應放置在車輪半徑的一半處,並均勻分佈。引入 cylinder_radius 和 cylinder_height 變數。cylinder_height 的值應適當,以便圓柱體始終比它們移除的材料的厚度更長。
程式碼

wheel_with_spherical_sides_and_holes.scad

$fa = 1;
$fs = 0.4;
wheel_radius=10;
side_spheres_radius=50;
hub_thickness=4;
cylinder_radius=2;
cylinder_height=2*wheel_radius;
difference() {
    // Wheel sphere
    sphere(r=wheel_radius);
    // Side sphere 1
    translate([0,side_spheres_radius + hub_thickness/2,0])
        sphere(r=side_spheres_radius);
    // Side sphere 2
    translate([0,- (side_spheres_radius + hub_thickness/2),0])
        sphere(r=side_spheres_radius);
    // Cylinder 1
    translate([wheel_radius/2,0,0])
        rotate([90,0,0])
        cylinder(h=cylinder_height,r=cylinder_radius,center=true);
    // Cylinder 2
    translate([0,0,wheel_radius/2])
        rotate([90,0,0])
        cylinder(h=cylinder_height,r=cylinder_radius,center=true);
    // Cylinder 3
    translate([-wheel_radius/2,0,0])
        rotate([90,0,0])
        cylinder(h=cylinder_height,r=cylinder_radius,center=true);
    // Cylinder 4
    translate([0,0,-wheel_radius/2])
        rotate([90,0,0])
        cylinder(h=cylinder_height,r=cylinder_radius,center=true);
}

練習
嘗試將以上車輪用於汽車的一個版本。
程式碼

car_with_wheels_with_spherical_sides_and_holes.scad

$fa = 1;
$fs = 0.4;
wheel_radius = 10;
base_height = 10;
top_height = 14;
track = 35;
wheel_width = 10;
body_roll = 0;
wheels_turn = 0;
side_spheres_radius=50;
hub_thickness=4;
cylinder_radius=2;
cylinder_height=2*wheel_radius;
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([0,0,wheels_turn])
    difference() {
        // Wheel sphere
        sphere(r=wheel_radius);
        // Side sphere 1
        translate([0,side_spheres_radius + hub_thickness/2,0])
            sphere(r=side_spheres_radius);
        // Side sphere 2
        translate([0,- (side_spheres_radius + hub_thickness/2),0])
            sphere(r=side_spheres_radius);
        // Cylinder 1
        translate([wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 2
        translate([0,0,wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 3
        translate([-wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 4
        translate([0,0,-wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
}
// Front right wheel
translate([-20,track/2,0])
    rotate([0,0,wheels_turn])
    difference() {
        // Wheel sphere
        sphere(r=wheel_radius);
        // Side sphere 1
        translate([0,side_spheres_radius + hub_thickness/2,0])
            sphere(r=side_spheres_radius);
        // Side sphere 2
        translate([0,- (side_spheres_radius + hub_thickness/2),0])
            sphere(r=side_spheres_radius);
        // Cylinder 1
        translate([wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 2
        translate([0,0,wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 3
        translate([-wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 4
        translate([0,0,-wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
}
// Rear left wheel
translate([20,-track/2,0])
    rotate([0,0,0])
    difference() {
        // Wheel sphere
        sphere(r=wheel_radius);
        // Side sphere 1
        translate([0,side_spheres_radius + hub_thickness/2,0])
            sphere(r=side_spheres_radius);
        // Side sphere 2
        translate([0,- (side_spheres_radius + hub_thickness/2),0])
            sphere(r=side_spheres_radius);
        // Cylinder 1
        translate([wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 2
        translate([0,0,wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 3
        translate([-wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 4
        translate([0,0,-wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
}
// Rear right wheel
translate([20,track/2,0])
    rotate([0,0,0])
    difference() {
        // Wheel sphere
        sphere(r=wheel_radius);
        // Side sphere 1
        translate([0,side_spheres_radius + hub_thickness/2,0])
            sphere(r=side_spheres_radius);
        // Side sphere 2
        translate([0,- (side_spheres_radius + hub_thickness/2),0])
            sphere(r=side_spheres_radius);
        // Cylinder 1
        translate([wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 2
        translate([0,0,wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 3
        translate([-wheel_radius/2,0,0])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_radius,center=true);
        // Cylinder 4
        translate([0,0,-wheel_radius/2])
            rotate([90,0,0])
            cylinder(h=cylinder_height,r=cylinder_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);

華夏公益教科書