第04章:参数、变量、函数、模块与作用域
1. 参数化设计的核心
OpenSCAD 最有价值的能力是参数化。参数化不是简单地把数字放到变量里,而是建立一套稳定的尺寸关系。一个好的 OpenSCAD 模型应该能回答:哪些参数允许用户修改?哪些尺寸由公式推导?哪些约束必须检查?哪些误差来自制造工艺?
wall = 2.4;
clearance = 0.3;
box = [80, 50, 24];
inner = [box[0] - 2*wall, box[1] - 2*wall, box[2] - wall];
如果模型中到处都是魔法数字,后期修改会非常痛苦。建议在文件顶部集中定义公开参数,在模块内部定义局部派生参数。
2. 模块 module
module 用于生成几何或组织子对象。它类似“可复用几何组件”。
module screw_hole(d = 3.2, h = 10, countersink = false) {cylinder(h = h, d = d, center = true);if (countersink)translate([0, 0, h/2 - 1]) cylinder(h = 2, d1 = 7, d2 = d, center = true);
}
调用时可以使用位置参数或命名参数:
screw_hole(3.2, 8, true);
screw_hole(d = 4.2, h = 12, countersink = true);
复杂项目推荐使用命名参数,尤其是参数数量较多时。
3. 函数 function
function 返回值,不直接生成几何。它适合计算尺寸、点集、角度、列表和条件结果。
function clamp(x, lo, hi) = min(max(x, lo), hi);
function polar(r, a) = [r * cos(a), r * sin(a)];points = [for (i = [0:5]) polar(20, i * 60)];
polygon(points);
函数应该保持纯粹:同样输入得到同样输出,不依赖隐含状态。这样更容易测试和复用。
4. 作用域
OpenSCAD 有全局作用域、模块作用域、函数作用域和 let 局部作用域。理解作用域可以避免变量名冲突。
thickness = 4;module plate(size = [40, 20]) {local_thickness = thickness;cube([size[0], size[1], local_thickness], center = true);
}
建议:
- 全局参数使用清晰长名,如
base_plate_thickness。 - 模块内部派生变量使用短名但不泄露到外部。
- 库文件避免使用容易冲突的全局变量。
- 对外参数尽量通过模块参数传入,而不是依赖全局变量。
5. children() 与高阶模块
children() 允许模块接收调用处的子对象,类似几何过滤器或包装器。
module mirrored_x() {children();mirror([1, 0, 0]) children();
}mirrored_x()translate([15, 0, 0]) cylinder(h = 5, d = 6);
这类模块适合封装对称、阵列、颜色、调试显示、局部坐标系和重复变换。
6. include 与 use
OpenSCAD 用 include 和 use 引入其他文件:
include <config.scad>
use <parts/bracket.scad>
一般理解:
include会引入变量、函数和模块,适合配置文件或共享常量。use更偏向只使用模块和函数,避免执行被引入文件中的顶层几何。
实际项目中建议把库文件设计为“顶层不生成几何”,这样无论 use 还是 include 都更可控。
7. 参数校验
OpenSCAD 没有强类型系统,但可以通过 assert 或条件输出保护模型。
module box_shell(size = [60, 40, 20], wall = 2) {assert(wall > 0, "wall must be positive");assert(size[0] > 2*wall && size[1] > 2*wall, "wall too thick for box size");difference() {cube(size, center = true);translate([0, 0, wall])cube([size[0]-2*wall, size[1]-2*wall, size[2]], center = true);}
}
公开库模块应尽量校验关键参数,例如负半径、零厚度、孔径大于外径、阵列数量小于 1 等。
8. 命名规范
推荐命名风格:
- 模块名使用小写加下划线:
mounting_plate。 - 函数名使用动词或数学含义:
bolt_circle_points、deg_to_rad。 - 参数名体现单位或语义:
hole_d、wall_t、clearance。 - 布尔参数使用
has_、use_、show_前缀。 - 避免
a、b、tmp这类无法说明设计意图的名字。
9. 可配置模型的分层
一个可维护模型通常分三层:
- 配置层:公开参数、产品规格、制造补偿。
- 零件层:各模块负责单个零件或几何特征。
- 装配层:放置零件、显示参考、导出单件或整件。
part = "assembly"; // "base", "cover", "assembly"if (part == "base") base();
else if (part == "cover") cover();
else assembly();
这种模式便于命令行批量导出不同零件。
10. 设计 API 的原则
当你编写给别人使用的 OpenSCAD 模块时,应像设计软件 API 一样认真:
- 参数默认值能生成有效模型。
- 参数顺序从最重要到最少改动。
- 单位、坐标原点和朝向在文档中明确。
- 不在模块内部随意改变全局特殊变量,必要时作为参数传入。
- 不把导出、调试、颜色和真实几何混在一起。
