znlgis 博客

GIS开发与技术分享

第03章:OpenSCAD 语言基础

1. 文件与语句

OpenSCAD 脚本通常保存为 .scad 文件。文件由变量赋值、模块调用、函数定义、模块定义、控制结构和特殊变量组成。语句以分号结束,语句块使用花括号。

size = 20;

module part() {
    cube([size, size, 5]);
}

part();

OpenSCAD 的语法看起来像编程语言,但它不是通用命令式语言。它更像声明式几何描述语言:脚本描述“要生成什么几何”,解释器根据上下文求值并构造几何树。

2. 注释

支持单行注释和块注释:

// 单行注释
cube(10); // 也可以写在语句后

/*
多行注释,适合临时说明设计意图。
不要长期保留大量废弃代码。
*/

复杂模型建议注释“为什么这样设计”,例如说明装配间隙、打印补偿、标准件来源,而不是解释 translate 是平移这类显而易见的语法。

3. 数据类型

常用数据类型包括:

  • 数字:13.14-5
  • 布尔:truefalse
  • 字符串:"M3 screw"
  • 向量/列表:[1, 2, 3][[0,0], [10,0], [10,5]]
  • 未定义值:undef
  • 范围:[0:5][0:2:10]

向量在 OpenSCAD 中非常重要,点、尺寸、颜色、旋转角、路径都用向量表示。

pos = [10, 0, 5];
size = [20, 10, 3];
translate(pos) cube(size);

4. 变量与重新赋值的理解

OpenSCAD 的变量更接近“在作用域内绑定一个值”,而不是传统语言中可不断改变的变量。后续章节会详细讲作用域。初学者先记住:不要用命令式循环累加的思维写 OpenSCAD,而应使用表达式、列表推导、递归或模块组合。

x = 10;
x = 20;
echo(x); // 在同一作用域中,最终绑定可能不同于命令式直觉,避免这样写

推荐写法是用清晰命名表达派生关系:

base_width = 40;
wall = 2;
inner_width = base_width - 2 * wall;

5. 运算符

常用运算包括:

  • 算术:+ - * / %
  • 比较:< <= > >= == !=
  • 逻辑:&& || !
  • 条件表达式:condition ? a : b
  • 向量索引:v[0]
  • 字符串连接和列表操作在不同版本支持能力需参考手册。

示例:

outer = 50;
wall = 3;
inner = outer - wall * 2;
valid = inner > 0;

if (valid)
    difference() {
        cube([outer, outer, 10], center = true);
        cube([inner, inner, 11], center = true);
    }
else
    echo("参数错误:壁厚过大");

6. 控制结构

OpenSCAD 常用 ifelseforintersection_forleteach 等结构。

for (x = [-20, 0, 20]) {
    translate([x, 0, 0]) cylinder(h = 5, d = 8);
}

for 在几何语境中通常表示“生成多个子对象”,而不是逐步改变状态。理解这一点能避免很多困惑。

7. echo 调试

echo() 用于输出变量和值:

radius = 12;
area = PI * radius * radius;
echo("area", area);

调试参数化模型时,echo 可用于检查派生尺寸、循环索引、选择分支和外部 -D 参数是否生效。复杂项目中建议输出关键参数,而不是在最终版本中保留大量噪声。

8. 特殊前缀字符

OpenSCAD 支持一些常用于调试和显示控制的前缀:

  • #:高亮显示对象,常用于检查切除体或定位参考体。
  • %:透明背景显示对象,不参与最终布尔结果的常规理解中常用于参考。
  • !:只显示当前对象,便于隔离调试。
  • *:禁用对象,相当于临时注释掉几何。

示例:

difference() {
    cube([40, 20, 10], center = true);
    #translate([0, 0, 0]) cylinder(h = 12, d = 8, center = true);
}

9. 单位约定

OpenSCAD 本身没有强制单位。3D 打印和机械零件通常把数值当作毫米。团队项目应在文件开头说明单位,并避免混用英寸、毫米和角度制。

// units: millimeter
plate_length = 80;
plate_width = 40;
plate_thickness = 4;

10. 语言学习重点

掌握语言基础时不要急着记住所有内置函数。最重要的是建立三种思维:

  1. 表达式思维:尺寸来自公式而不是手工改多个数字。
  2. 组合思维:复杂形体来自模块组合和布尔运算。
  3. 生成思维:阵列、曲线、孔位、齿形都可以由列表和循环生成。