OpenSCAD用户手册/变换
基本概念
[编辑]顾名思义,变换会以各种方式影响子节点,例如对它们进行移动、旋转或缩放。级联变换(cascading transformations)则常用于将多种变换作用于一个最终子对象 。通过嵌套语句即可实现级联变换,即:
rotate([45,45,45]) translate([10,20,30]) cube(10);
利用'{' 与 '}'围起子节点树,即可将变换应用于这一组子节点,如:
translate([0,0,-5])
{
cube(10);
cylinder(r=5,h=10);
}
变换要写于其影响的对象之前。
可以将类似于translate(平移)、mirror(镜像)与scale(缩放)这样的命令想象为动词。而将color(上色)这样的命令想象为描述对象的形容词。
请注意,变换命令后不加分号。
高级概念
[编辑]由于OpenSCAD采用不同的库来实现其中功能,因此在用F5预览变换的行为时可能会产生一些不一致的现象。传统的变换(平移,旋转,缩放,镜像与multmatrix)都采用OpenGL实现预览。而其他更为高级的变换,如resize,则用CGAL进行处理,其行为就像CSG操作,影响的是对象本身,而不仅仅是对其进行变换。特别是这会影响修饰符的显示,尤其是"#"与"%",where the highlight may not display intuitively。such as highlighting the pre-resized object, but highlighting the post-scaled object.
scale
[编辑]scale命令利用指定的向量来缩放其子元素。参数名可以不写。
用例: scale(v = [x, y, z]) { ... }
cube(10);
translate([15,0,0]) scale([0.5,1,2]) cube(10);
注意: 不要用负数作为缩放值。负缩放值的效果可以在预览中看到,但是通过CGAL渲染时会导致不可预测的错误。如需输入负值,可用mirror()函数代替。
resize
[编辑]根据指定的x、y、z修改子对象的尺寸。
resize()函数由CGAL来实现,就像render()这样的函数一样要处理整个几何体,因此就算是在预览模式下也要花上些时间来进行处理。
用例:
// 将球体在x轴上的直径拓展至30,在y轴上的直径拓展至60,在z轴上的直径拓展至10。
resize(newsize=[30,60,10]) sphere(r=10);
如果x、y或z为0,那么原对象在对应维度上保持不变。
// 将大小为1x1x1的立方体调整为2x2x1
resize([2,2,0]) cube();
如果把'auto'参数设置为true,则resize函数将对参数值为0的维度进行自动缩放。例如:
// 将大小为1x2x0.5的长方体调整为7x14x3.5
resize([7,0,0], auto=true) cube([1,2,0.5]);
'auto'参数也可用于仅对一个维度进行自动缩放而其他维度保持不变的情况。
// 将原长方体调整为10x8x1。请注意,其z维度保持不变。
resize([10,0,0], auto=[true,true,false]) cube([5,4,1]);
rotate
[编辑]令子元素绕坐标轴或任意轴旋转'a'度。如果将参数按下列相同顺序指定,则可省略参数名。
//用例:
rotate(a = deg_a, v = [x, y, z]) { ... }
// 或
rotate(deg_a, [x, y, z]) { ... }
rotate(a = [deg_x, deg_y, deg_z]) { ... }
rotate([deg_x, deg_y, deg_z]) { ... }
参数'a'(deg_a)可以是一个数组,其语法如上所示;当deg_a是一个数组时,将忽略参数'v'。而此时的'a'则指定的是令物体绕多个坐标轴进行旋转,而旋转的执行顺序为:x, y, z。这就意味着下列代码:
rotate(a=[ax,ay,az]) {...}
等价于(旋转顺序会影响最终旋转结果):
rotate(a=[0,0,az]) rotate(a=[0,ay,0]) rotate(a=[ax,0,0]) {...}
可选参数'v'是一个向量,您可借此令对象绕任意轴进行旋转。
例如,为了让一个对象上下颠倒翻转过来,您可以令此对象绕'y'轴旋转180度。
rotate(a=[0,180,0]) { ... }
常用化简写法为:
rotate([0,180,0]) { ... }
在指定单个坐标轴时,通过设置参数'v'也能令对象绕坐标轴进行旋转。例如,以下代码是上述代码的等效实现,它令对象仅绕轴y进行旋转
rotate(a=180, v=[0,1,0]) { ... }
在指定单个坐标轴时,参数'v'是一个定义任意旋转轴的向量;这与此前提及的绕多个坐标轴进行旋转并不相同。例如,令对象绕向量[1,1,0]定义的轴旋转45度的代码为
rotate(a=45, v=[1,1,0]) { ... }
利用单个标量参数令对象绕Z轴进行旋转。这种方法在2D环境中十分有用,此时通常仅绕一种轴进行旋转。例如:
rotate(45) square(10);
旋转规则提示
[编辑]
针对以下情况:
rotate([a, b, c]) { ... };
"a"是一个令对象从+Y轴方向至+Z轴方向绕X轴旋转的旋转角。
"b"是一个令对象从+Z轴方向至+X轴方向绕Y轴旋转的旋转角。
"c"是一个令对象从+X轴方向至+Y轴方向绕Z轴旋转的旋转角。
这些情况均遵从右手法则。右手拇指指向旋转轴的正方向,则其他手指的自然弯曲方向即为旋转方向。
因此,如果"a"恒为0,且对"b"与"c"进行适当的计算,便可将rotate()当作球坐标系来使用。
所以,为了构建从原点至(x,y,z)的圆柱体,可以这样编写代码:
x= 10; y = 10; z = 10; // 圆柱体的端点坐标
length = norm([x,y,z]); // 半径距离
b = acos(z/length); // 倾角(inclination angle)
c = atan2(y,x); // 方位角(azimuthal angle)
rotate([0, b, c])
cylinder(h=length, r=0.5);
%cube([x,y,z]); // 圆柱体的端点应与立方体的交点重合
translate
[编辑]沿指定向量平移(移动)子元素。可省略参数名。
示例: translate(v = [x, y, z]) { ... }
cube(2,center = true);
translate([5,0,0])
sphere(1,center = true);
mirror
[编辑]基于原点对平面上的子元素进行镜像操作。传入mirror()函数的参数为交于原点且用于镜像对象的平面上的法向量。
函数签名:
[编辑]mirror(v= [x, y, z] ) { ... }
Examples
[编辑]左侧为原始对象。请注意,镜像并非复制品。而是像rotate与scale函数那样,改变对象本身。
-
hand(); // 原始对象
mirror([1,0,0]) hand();
-
hand(); // 原始对象
mirror([1,1,0]) hand();
-
hand(); // 原始对象
mirror([1,1,1]) hand();
rotate([0,0,10]) cube([3,2,1]); mirror([1,0,0]) translate([1,0,0]) rotate([0,0,10]) cube([3,2,1]);
multmatrix
[编辑]为所有子元素的几何体乘上指定的4x4变换矩阵。
用法: multmatrix(m = [...]) { ... }
以下为矩阵中前三行每一元素的内含解析:
[Scale X] | [Scale X sheared along Y] | [Scale X sheared along Z] | [Translate X] |
[Scale Y sheared along X] | [Scale Y] | [Scale Y sheared along Z] | [Translate Y] |
[Scale Z sheared along X] | [Scale Z sheared along Y] | [Scale Z] | [Translate Z] |
第四行用于在3D环境中定义对象的视图。在OpenSCAD中没有用到这一点,应将其设置为[0,0,0,1]。
以下示例为将对象在XY平面内旋转45度,并按[10,20,30]进行平移,其效果与translate([10,20,30]) rotate([0,0,45])相同。
angle=45;
multmatrix(m = [ [cos(angle), -sin(angle), 0, 10],
[sin(angle), cos(angle), 0, 20],
[ 0, 0, 1, 30],
[ 0, 0, 0, 1]
]) union() {
cylinder(r=10.0,h=10,center=false);
cube(size=[10,10,10],center=false);
}
以下为令模型倾斜(skew)的示例,这是不能由其他变换来实现的。此例也展示了可将矩阵置于一个变量中。
M = [ [ 1 , 0 , 0 , 0 ],
[ 0 , 1 , 0.7, 0 ], // "0.7"为倾斜值;在这里,它令对象偏离y轴发生倾斜
[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 0 , 1 ] ] ;
multmatrix(M) { union() {
cylinder(r=10.0,h=10,center=false);
cube(size=[10,10,10],center=false);
} }
不够刺激?
[编辑]来这里学习更多的相关知识吧:
color
[编辑]利用指定的RGB颜色 + alpha值来显示子元素。此函数仅用于F5预览,因为CGAL 与 STL (F6)当前还不支持上色。如果未指定alpha值,其默认值为1.0(不透明)。
函数签名:
[编辑]color( c = [r, g, b, a] ) { ... } color( c = [r, g, b], alpha = 1.0 ) { ... } color( "#hexvalue" ) { ... } color( "colorname", 1.0 ) { ... }
请注意,r, g, b, a
值仅限于[0,1]范围中的浮点值,而非相对传统的{ 0 ... 255 }整数值。然鹅,没有神马能阻止您通过适当的比例转换方式color([ R/255, G/255, B/255 ]) { ... }
来运用{0 ... 255}范围的R, G, B
值:
[请注意: 需要使用版本 2011.12]
可以通过颜色名称(大小写不敏感)来定义颜色。例如,要创建一个红色的球体,您可以写color("red") sphere(5);
。对于采用颜色名称指定颜色的方式而言,还要为alpha值额外指定一个参数:color("Blue",0.5) cube(5);
[请注意: 需要使用版本 2019.05]
表示颜色的16进制值有4种格式:#rgb
, #rgba
, #rrggbb
与 #rrggbbaa
。如果alpha值以单独的16进制参数给出,the alpha parameter will take precedence.
可用的颜色名称都取自万维网联盟的[1]。下面给出一幅颜色名称图表,
(请注意,包括slategrey/slategray等在内的grey/gray拼写都是合法的):
|
|
|
|
|
示例
[编辑]这里给出一个绘制多色波浪对象的代码片段:
for(i=[0:36]) {
for(j=[0:36]) {
color( [0.5+sin(10*i)/2, 0.5+sin(10*j)/2, 0.5+sin(10*(i+j))/2] )
translate( [i, j, 0] )
cube( size = [1, 1, 11+10*cos(10*i)*sin(10*j)] );
}
}
↗ 由于 -1<=sin(x)<=1,因此 0<=(1/2 + sin(x)/2)<=1 ,这样即可为RGB分量赋予[0,1]区间中的颜色值。
示例2
[编辑]在本例中,我们将基于参数来选择性地设置颜色,这里使用了如下技巧:
module myModule(withColors=false) {
c=withColors?"red":undef;
color(c) circle(r=10);
}
将colorname设置为undef将保持其默认颜色。
offset
[编辑][请注意: 需要使用版本 2015.03]
offset函数根据指定的值令2D轮廓外向或内向移动。
- 通过正偏移外表面与负偏移内表面之差可方便地绘制薄壁。
- Fillet: offset(r=-3) offset(delta=+3) rounds all inside (concave) corners, and leaves flat walls unchanged. However, holes less than 2*r in diameter will vanish.
- Round: offset(r=+3) offset(delta=-3) rounds all outside (convex) corners, and leaves flat walls unchanged. However, walls less than 2*r thick will vanish.
参数
- r | delta
- 双精度浮点数(double)。偏移多边形的值。此值为负时,令多边形进行内向偏移。参数r指定的是用于生成圆角的半径,使用delta则采用直边。
- chamfer
- 布尔值(boolean)。 (默认值为false) 在使用delta参数时,此标志定义了是(以直线进行切割)否(扩展至边的交点)应当对边进行倒角。
示例
// 示例1
linear_extrude(height = 60, twist = 90, slices = 60) {
difference() {
offset(r = 10) {
square(20, center = true);
}
offset(r = 8) {
square(20, center = true);
}
}
}
// 示例2
module fillet(r) {
offset(r = -r) {
offset(delta = r) {
children();
}
}
}
minkowski
[编辑]显示子节点的闵可夫斯基和(minkowski sum)。
用例:
假设您有一个平整的立方体,并希望对其进行倒圆角操作。有很多方法可以达到此目的,minkowski就是一种简单易用的方法。先来制作待处理的立方体与圆柱体:
$fn=50;
cube([10,10,1]);
cylinder(r=2,h=1);
接着,令它们执行闵可夫斯基和(请注意,立方体的外形尺寸现在为14x2,10+2+2 = 14个单位,而高的2个单位则为两者的高之和):
$fn=50;
minkowski()
{
cube([10,10,1]);
cylinder(r=2,h=1);
}
请注意:第二个对象的原点(origin)将用于求和运算。如果第二个对象并未对齐于原点,则闵可夫斯基和的结果将是不对称的。下列两种闵可夫斯基和是不同的:第一种会把原始的立方体在正负每个方向各展开0.5个单位。而第二种会将原始立方体在每个正方向上扩展+1,却不会在负方向上对其进行展开。
minkowski() {
cube([10, 10, 1]);
cylinder(1, center=true);
}
minkowski() {
cube([10, 10, 1]);
cylinder(1);
}
hull
[编辑]显示子节点的凸包(convex hull)。
用例:
hull() {
translate([15,10,0]) circle(10);
circle(10);
}
采用2D参数的hull函数只能计算出2D结果;在Z轴方向上平移2D组件不会产生任何效果。
组合变换
[编辑]在把多种变换组合在一起时,要按从右至左的次序进行处理。例如,
rotate( ... ) translate ( ... ) cube(5) ;
将首先平移立方体,再以平移距离为半径的弧(弧度为rotate中所指定)进行移动。
translate ( ... ) rotate( ... ) cube(5) ;
将首先旋转立方体,再将其按平移定义的偏移量进行平移。
color("red") translate([0,10,0]) rotate([45,0,0]) cube(5); color("green") rotate([45,0,0]) translate([0,10,0]) cube(5);