跳转到内容

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

华夏公益教科书