Openscad是3D建模的软件,与其它常见的3D建模软件不同,Openscad以程序的形式生成3D模型。这种方式特别适合制作相对规整的模型,不太适合制作艺术品。
Openscad的语法相对简单,一页纸就涵盖了所有的函数,可在使用时查阅cheatsheet。
一些注意事项
- Openscad的变量值在编译时确定,有点像其它编程语言的常量,但是如果在多个地方定义了变量,这个变量的实际值为最后一次定义的值。
- 使用
*
移除后面的模型。与使用//
注释只影响当前行不同,使用*
会移除后面的完整模型。*translate([50, 0, 0]) cube([50, 50, 50], false);
- if语句在function里不可用,但三目运算
= ? ... : ...
可以 - 可使用
include
或use
导入其它scad文件。include
导入当于复制粘贴,use
导入只导入module与function定义,其它命令都会被忽略。 - 可使用
import
指令导入stl文件,用于展示。
Openscad示例
// cheatsheet: https://www.openscad.org/cheatsheet/index.html?version=2019.05
// Number of fragments, larger number makes the curved surface looks smoother
// Has no effect on the printed model
$fn = 80;
// Set default display color for following objects
// RGB color also works, color([0.5, 0.3, 0.8])
color("green")
// Use intersection to remove all parts with no overlapping
intersection(){
// Use * to remove the following object
*translate([50, 0, 0])
cube([50, 50, 50], true);
// Use # to hightlight the object
#cylinder( 25, d1=29, d2=29 );
// Use % to make the object transparent
%sphere(20);
// Use ! to hide all objects except the current one
// !sphere(20);
rotate(a=[0,180,0]) {
cylinder(h=105, r1=2.5, r2=9.5, center=true);
};
}
// Use difference to remove the following parts from the first object
translate([0, 0, 120])
difference(){
sphere(40);
cylinder(r=20, h=200, center=true);
}
color([0.2, 0.5, 0.8])
// Note for loop does a union for you
translate([50, 0, 0])
for(i = [10:5:30]){
x = i*2;
translate([x, i, 0])
cylinder(h=80, r1=5, r2=i, center=true);
};
// Intersection for loop
color([1, 0.5, 0.8])
// Note for loop does a union for you
translate([110, 30, 80])
rotate([180, 0, 120])
intersection_for(i = [10:10:30]){
translate([i/2, i/2, 0])
cylinder(h=80, r1=5, r2=i, center=true);
};
// Use module to create reusable objects
module pyramid(loc=[0, 0, 0], height=22){
// Create a pyramid from a 2D square using linear_extrude
translate(loc)
linear_extrude(height=height, scale=0)
square(height, true);
}
pyramid([0, -50, 0], 30);
pyramid([0, -100, 0], 40);
// Use `children()` in module to apply command to all child components
// Use `children(0)` to refer to the first child component
module move_to(loc){
translate(loc) children();
}
color("lightgreen")
move_to([0, 40, 0])
pyramid(height=28);
// Create donuts using rotate_extrude
// rotate_extrude first rotate a 2D shape 90deg around x-axis, then rotate around z-axis
color("pink")
translate([0, 0, 80])
rotate_extrude(angle=360, $fn=100)
translate([30, 0, 0])
circle(10, $fn=100);
// You can import 2D shape and generate a 3D shape from it
color("blue")
translate([0, 100, 0])
linear_extrude(height=22)
scale(0.1)
// In Inkscape, you can use Path-Trace Bitmap to create path from bitmap automatially
import(file="Io.svg");
// Include a file, everything in that file will be included
// include <myfile.scad>
// Use a lib, only module and function definition will be imported
// use <myfile.scad>
// When applying + or - on two vectors, the two vectors are added or subtracted element-wise.
// When applying * on two vectors, the result is a single number, the dot product of the two vectors
从命令行导出STL
从命令行导出STL的优点是可以批量导出STL。可以用下面的脚本辅助导出STL:
# Filename scad_to_stl.py
# Usage
# Convert input scad file to stl
# python3 scad_to_stl.py -i myfile.scad -o myfile-top.stl --append ' SHOW_TOP=1; '
#
#
from subprocess import check_output
import logging
from logging import info
logging.basicConfig(format='%(name)s - %(levelname)s - %(message)s', level=logging.INFO)
_top_opts = ' TShell=1; BShell=0; FPanL=0; BPanL=0;PanelFeatures=0; '
_bot_opts = ' TShell=0; BShell=1; FPanL=0; BPanL=0;PanelFeatures=0; '
_front_opts = ' TShell=0; BShell=0; FPanL=1; BPanL=0;PanelFeatures=1; '
_back_opts = ' TShell=0; BShell=0; FPanL=0; BPanL=1;PanelFeatures=1; '
_sides = dict(top=_top_opts,
bottom=_bot_opts,
front=_front_opts,
back=_back_opts)
def scad_to_stl(p_scad, p_stl, append=''):
with open(p_scad, 'r') as f:
content = f.read() + ' ' + append
# https://github.com/openscad/openscad/issues/615
# openscad /dev/null -D "cube([2,3,4]);" -o dump.png
resp = check_output(['openscad', '/dev/null', '-D', content, '-o', p_stl])
info(f'resp: {resp}')
if __name__ == "__main__":
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", type=str, help="Input scad file")
ap.add_argument("-s", "--side", type=str,
default='',
help="Side to export to stl file, only for https://github.com/jbebel/Ultimate-Box-Maker.\nOptions: top, bottom, front, back")
ap.add_argument("--append", required=False, type=str,
default='',
help="Additional content to append to the input file, you can use this option to override variables in scad source")
ap.add_argument("-o", "--output", type=str, help="Output stl file")
args = vars(ap.parse_args())
side = args['side']
opts = _sides.get(side, '')
append = opts + args['append']
info(f'Convert scad to stl using additional opts: {append}')
scad_to_stl(args['input'], args['output'], append)
如果你的模型会有多个面需要打印,可以利用opencad变量值以最后一次定义为准的特点,在openscad源码里定义变量用于控制某个面是否显示,在导出时配置需要覆盖的参数,例如
python3 scad_to_stl.py -i myfile.scad -o myfile-top.stl --append ' SHOW_TOP=1; '
Openscad库
MCAD包含了多面体,文本,数据计算等工具。