跳转到内容

OpenSCAD 用户手册/变换

来自维基教科书,开放的世界,开放的书籍

基本概念

[编辑 | 编辑源代码]

变换会影响它们的子节点,顾名思义,它们会以各种方式变换它们,例如移动、旋转或缩放子节点。变换写在它们影响的对象之前,例如

translate([10,20,30])
    cube(10);

注意,变换命令后面没有分号。可以使用 '{' 和 '}' 将子树括起来,将变换应用于一组子节点,例如

translate([0,0,-5])
{
    cube(10);
    cylinder(r=5,h=10);
}

级联变换用于对最终子节点应用各种变换。级联是通过嵌套语句实现的,例如

rotate([45,45,45])
    translate([10,20,30])
        cube(10);
在组合变换时,顺序很重要

组合变换是一个顺序过程,从右到左进行。考虑以下两个变换

color("red")   translate([0,10,0])  rotate([45,0,0])     cube(5);
color("green") rotate([45,0,0])     translate([0,10,0])  cube(5);

虽然它们包含相同的操作,但第一个围绕原点旋转一个立方体,然后根据平移指定的偏移量移动它,最后将其涂成红色。相比之下,第二个序列首先移动一个立方体,然后围绕原点旋转它,最后将其涂成绿色。在这种情况下,旋转会导致立方体沿以原点为中心的弧线移动。这条弧线的半径是距原点的距离,这是由前面的平移设置的。旋转和平移变换的不同顺序会导致立方体最终出现在不同的位置。

高级概念

[编辑 | 编辑源代码]

由于 OpenSCAD 使用不同的库来实现功能,这可能会导致变换的 F5 预览行为出现一些不一致。传统的变换(平移、旋转、缩放、镜像和 multimatrix)在预览中使用 OpenGL 执行,而其他更高级的变换,如调整大小,则执行 CGAL 操作,表现得像 CSG 操作,影响的是底层对象,而不仅仅是变换它。特别是这会影响修饰符字符(特别是“#”和“%”)的显示,其中突出显示可能不会直观地显示,例如突出显示调整大小前的对象,但突出显示缩放后的对象。

使用指定的向量缩放其子元素。参数名称是可选的。

Usage Example:
scale(v = [x, y, z]) { ... }
cube(10);
translate([15,0,0]) scale([0.5,1,2]) cube(10);

Image showing result of scale() transformation in OpenSCAD

调整大小

[编辑 | 编辑源代码]

修改子对象的尺寸以匹配给定的 x、y 和 z。

resize() 是一个 CGAL 操作,与 render() 等其他操作一样,它使用完整的几何体进行操作,因此即使在预览中,这也会花费时间来处理。


用法示例

// resize the sphere to extend 30 in x, 60 in y, and 10 in the z directions.
resize(newsize=[30,60,10]) sphere(r=10);

OpenSCAD Resize example ellipse

如果 x、y 或 z 为 0,则该维度将保持原样。

// resize the 1x1x1 cube to 2x2x1
resize([2,2,0]) cube();

如果 'auto' 参数设置为 true,则会自动缩放任何 0 维度以匹配。例如。

// resize the 1x2x0.5 cube to 7x14x3.5
resize([7,0,0], auto=true) cube([1,2,0.5]);

'auto' 参数也可以在你只想自动缩放一个维度,而保持其他维度不变的情况下使用。

// resize to 10x8x1. Note that the z dimension is left alone.
resize([10,0,0], auto=[true,true,false]) cube([5,4,1]);

围绕坐标系的轴或围绕任意轴将它的子节点旋转 'a' 度。如果参数按指定的顺序给出,则参数名称是可选的。

//Usage:
rotate(a = deg_a, v = [x, y, z]) { ... }  
// or
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]) {...}

例如,要将对象翻转过来,你可以围绕 'y' 轴将对象旋转 180 度。

rotate(a=[0,180,0]) { ... }

这通常简化为

rotate([0,180,0]) { ... }

可选参数 'v' 是一个向量,它决定了对象围绕其旋转的任意轴。

在指定单个轴时,'v' 参数允许你指定哪个轴是旋转的基础。例如,与上面等效,围绕 y 旋转

rotate(a=180, v=[0,1,0]) { ... }

在指定单个轴时,'v' 是一个向量,定义了旋转的任意轴;这与上面的多个轴不同。例如,围绕由向量 [1,1,0] 定义的轴将对象旋转 45 度,

rotate(a=45, v=[1,1,0]) { ... }

image of result of rotate() transformation in OpenSCAD

使用单个标量参数旋转围绕 Z 轴旋转。这在 2D 上下文中很有用,因为 Z 轴是唯一的旋转轴。例如

rotate(45) square(10);

Result of OpenSCAD rotate(45) as 2D render

旋转规则帮助
[编辑 | 编辑源代码]
右手定则


对于

rotate([a, b, c]) { ... };

"a" 是围绕 X 轴的旋转,从 +Y 轴到 +Z 轴。
"b" 是围绕 Y 轴的旋转,从 +Z 轴到 +X 轴。
"c" 是围绕 Z 轴的旋转,从 +X 轴到 +Y 轴。

这些都是右手定则的情况。将你的右手拇指指向正轴,你的手指显示旋转的方向。


因此,如果 "a" 固定为零,并且 "b" 和 "c" 被适当操作,这就是球坐标系
因此,要从原点构建一个到另一个点 (x,y,z) 的圆柱体

x= 10; y = 10; z = 10; // point coordinates of end of cylinder
 
length = norm([x,y,z]);  // radial distance
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]); // corner of cube should coincide with end of cylinder

Example of OpenSCAD Rotate() used as a spherical coordinate system.

平移(移动)其子元素沿着指定的向量。参数名称是可选的。

Example:
translate(v = [x, y, z]) { ... }
cube(2,center = true); 
translate([5,0,0]) 
   sphere(1,center = true);

image of result of the translate() transformation in OpenSCAD

将子元素变换为原始元素的镜像,就好像它是通过穿过原点的平面看到的镜像一样。mirror() 的参数是穿过原点的镜像平面的法向量,这意味着垂直于平面出来的向量。原始对象的每个坐标都将被改变,使其在该平面的另一侧与平面上的最接近点等距。例如,mirror([1,0,0])对应于指向 x 轴方向的法向量,会产生一个对象,使得所有正 x 坐标变为负 x 坐标,所有负 x 坐标变为正 x 坐标。

函数签名

[编辑 | 编辑源代码]
mirror(v= [x, y, z] ) { ... }

原始模型在右侧。注意,镜像不会复制。与旋转和缩放一样,它会改变物体。

rotate([0,0,10]) cube([3,2,1]);
mirror([1,0,0]) translate([1,0,0]) rotate([0,0,10]) cube([3,2,1]);

image of the result of the mirror() transformation in OpenSCAD

multmatrix

[编辑 | 编辑源代码]

将所有子元素的几何图形乘以给定的仿射变换矩阵,其中矩阵为 4×3 - 一个包含 4 个元素的 3 个行向量的向量,或一个 4×4 矩阵,其中第 4 行始终强制为 [0,0,0,1]。

用法:multmatrix(m = [...]) { ... }

以下是您可以使用矩阵中独立元素(前三行)进行的操作的细分。

X 方向缩放Y 方向剪切 XZ 方向剪切 XX 方向平移
X 方向剪切 YY 方向缩放Z 方向剪切 YY 方向平移
X 方向剪切 ZY 方向剪切 ZZ 方向缩放Z 方向平移

第 4 行强制为 [0,0,0,1] 并且可以省略,除非您在传递给 multmatrix 之前组合矩阵,因为它不会在 OpenSCAD 中处理。每个矩阵都对给定几何图形的点进行操作,就好像每个顶点都是一个包含 4 个元素的向量,由一个 3D 向量组成,其中隐式地将 1 作为其第 4 个元素,例如 v=[x, y, z, 1]。m 的隐式第四行的作用是保留向量第 4 个元素中的隐式 1,从而使平移能够正常工作。因此,multmatrix 操作对每个顶点 v 执行 m*v。m 中未指定的任何元素(除了第 4 行)都被视为零。

此示例在 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);
}

以下示例演示了通过矩阵乘法组合仿射变换矩阵,在最终版本中产生等效于 rotate([0, -35, 0]) translate([40, 0, 0]) Obj(); 的变换。请注意,sin 函数上的符号似乎与上面的示例不同,因为正符号必须按 x 到 y、y 到 z、z 到 x 的顺序排列,以便旋转角度对应于右手坐标系中绕另一个轴的旋转。

module Obj() {
   cylinder(r=10.0,h=10,center=false);
   cube(size=[10,10,10],center=false);
}

// This itterates into the future 6 times and demonstrates how multimatrix is moving the object around the center point
for(time = [0 : 15 : 90]){
    y_ang=-time;
    mrot_y = [ [ cos(y_ang), 0,  sin(y_ang), 0],
               [         0,  1,           0, 0],
               [-sin(y_ang), 0,  cos(y_ang), 0],
               [         0,  0,           0, 1]
             ];
    mtrans_x = [ [1, 0, 0, 40],
                 [0, 1, 0,  0],
                 [0, 0, 1,  0],
                 [0, 0, 0,  1]
               ];

    echo(mrot_y*mtrans_x);
    
    // This is the object at [0,0,0]
    Obj();
    
    // This is the starting object at the [40,0,0] coordinate
    multmatrix(mtrans_x) Obj();
    
    // This is the one rotating and appears 6 times
    multmatrix(mrot_y * mtrans_x) Obj();
};

此示例倾斜了模型,这在其他变换中是不可能的。

M = [ [ 1  , 0  , 0  , 0   ],
      [ 0  , 1  , 0.7, 0   ],  // The "0.7" is the skew value; pushed along the y axis as z changes.
      [ 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); 
} }

此示例展示了如何使用 multmatrix 向量变换向量,就像这样,点数组(多边形)中的所有点都可以按顺序变换。向量 (v) 使用旋转矩阵 (m) 变换,产生新的向量 (vtrans),它现在已旋转,并且正在使立方体沿半径为 v 的圆形路径绕 z 轴移动,而不会旋转立方体。

angle=45;
 m=[
        [cos(angle), -sin(angle), 0, 0],
        [sin(angle),  cos(angle), 0, 0],
        [         0,           0, 1, 0]
   ];
              
v=[10,0,0];
vm=concat(v,[1]); // need to add [1]
vtrans=m*vm;
echo(vtrans);
translate(vtrans)cube();

更多?

[编辑 | 编辑源代码]

在这里了解更多信息

使用指定的 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 }。但是,没有什么可以阻止您使用 {0 ... 255} 中的R, G, B 值,并进行适当的缩放:color([ R/255, G/255, B/255 ]) { ... }

[注意: 需要版本 2011.12] 颜色也可以通过名称定义(不区分大小写)。例如,要创建红色球体,您可以编写 color("red") sphere(5);。alpha 作为命名颜色的额外参数指定:color("Blue",0.5) cube(5);

[注意: 需要版本 2019.05] 十六进制值可以用 4 种格式给出,#rgb#rgba#rrggbb#rrggbbaa。如果 alpha 值在十六进制值和作为单独的 alpha 参数中给出,则 alpha 参数优先。

警告: alpha 处理(透明度)对顺序敏感。透明对象必须列在不透明对象之后才能正确显示。某些涉及多个透明对象的组合无法正确处理。请查看问题#1390

可用的颜色名称取自万维网联盟的SVG 颜色列表。颜色名称图表如下所示,
(注意,灰色/灰色的两种拼写,包括深石板灰/深石板灰等,都是有效的):

紫色
淡紫色
蓟色
李子色
紫罗兰色
兰花色
紫红色
洋红色
中兰花紫
中紫色
蓝紫色
深紫色
深兰花紫
深洋红色
紫色
靛蓝色
深石板蓝
石板蓝
中石板蓝
红色
印度红
淡珊瑚色
鲑鱼色
深鲑鱼色
淡鲑鱼色
红色
深红色
砖红色
深红色
蓝色
水色
青色
淡青色
淡绿宝石色
碧绿色
绿松石色
中绿松石色
深绿松石色
军绿色
钢蓝色
淡钢蓝色
粉蓝色
淡蓝色
天蓝色
淡天蓝色
深天蓝色
道奇蓝
矢车菊蓝
皇家蓝
蓝色
中蓝色
深蓝色
海军蓝
午夜蓝
粉色
粉色
淡粉色
热粉色
深粉色
中紫红色
淡紫红色
绿色
黄绿色
黄绿色
草绿色
酸橙色
青绿色
淡绿色
淡绿色
中春绿色
春绿色
中海绿色
海绿色
森林绿
绿色
深绿色
黄绿色
橄榄褐色
橄榄色
深橄榄绿
中碧绿色
深海绿色
淡海绿色
深青色
蓝绿色
橙色
淡鲑鱼色
珊瑚色
番茄色
橙红色
深橙色
橙色
黄色
金色
黄色
淡黄色
柠檬薄纱色
淡金黄色
番木瓜色
鹿皮色
桃色
淡金黄色
卡其色
深卡其色
棕色
玉米色
淡杏色
肉色
土黄色
小麦色
褐色
棕褐色
玫瑰棕色
沙棕色
金黄色
深金黄色
秘鲁色
巧克力色
马鞍褐色
赭石色
棕色
栗色
白色
白色
雪白色
蜜黄色
薄荷奶油色
蔚蓝色
淡蓝色
幽灵白
烟白色
贝壳色
米色
旧蕾丝色
花白色
象牙色
古董白
亚麻色
淡紫红色
雾玫瑰色
灰色
浅灰色
淡灰色
银色
深灰色
灰色
暗淡灰色
淡石板灰
石板灰
深石板灰
黑色
3D 多色正弦波

这是一个绘制波浪状多色对象的代码片段。

  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] 区间内。

基于维基百科的“网页颜色”的图表

在您想要根据参数可选地设置颜色时,可以使用以下技巧。

 module myModule(withColors=false) {
    c=withColors?"red":undef;
    color(c) circle(r=10);
 }

将 colorname 设置为 undef 会保留默认颜色。

[注意: 需要版本 2015.03]

偏移操作从现有轮廓生成新的二维内部或外部轮廓。它有两种操作模式:径向和增量。

  • 径向方法创建新的轮廓,就像半径为 r 的圆绕原始轮廓的外部(r > 0)或内部(r < 0)旋转一样。
  • 增量方法创建新的轮廓,其边与原始轮廓之间保持固定距离,向外(增量 > 0)或向内(增量 < 0)。

构造方法生成位于原始轮廓内部或外部的轮廓。对于使用增量的轮廓,当轮廓绕过拐角时,可以可选地提供倒角。

偏移操作对于创建薄壁很有用,方法是从原始轮廓中减去负偏移构造,或从正偏移构造中减去原始轮廓。

偏移操作可用于模拟一些常见的实体建模操作。

  • 圆角:offset(r=-3) offset(delta=+3) 对所有内部(凹)拐角进行圆角处理,并保持平坦的墙壁不变。但是,直径小于 2*r 的孔会消失。
  • 圆形:offset(r=+3) offset(delta=-3) 对所有外部(凸)拐角进行圆角处理,并保持平坦的墙壁不变。但是,厚度小于 2*r 的墙壁会消失。
参数

第一个参数可以不带名称传递,在这种情况下,它将被视为下面的 r 参数。如果使用所有其他参数,则必须命名。

rdelta

数字。偏移多边形的量。为负值时,多边形向内偏移。
  • r(如果未命名,则为默认参数)指定绕轮廓旋转的圆的半径,可以是内部或外部。此模式生成圆角。名称可以省略;也就是说,offset(c) 等效于 offset(r=c)
  • 增量指定新轮廓与原始轮廓的距离,因此会再现有角度的拐角。在轮廓会与自身交叉的地方不会生成内部周长。
倒角
布尔值。 (默认值 false)在使用增量参数时,此标志定义边缘是否应倒角(用直线切断)或不倒角(扩展到它们的交点)。此参数对径向偏移没有影响。

$fa$fs$fn

可以使用 圆形分辨率 特殊变量来控制径向偏移生成的曲线的平滑度或面尺寸。它们对增量偏移没有影响。
正 r/增量值
负 r/增量值
不同参数的结果。黑色多边形是 offset() 操作的输入。

示例

示例 1:结果。
// Example 1
 
linear_extrude(height = 60, twist = 90, slices = 60) {
   difference() {
     offset(r = 10) {
      square(20, center = true);
     }
     offset(r = 8) {
       square(20, center = true);
     }
   }
 }
// Example 2
 
module fillet(r) {
   offset(r = -r) {
     offset(delta = r) {
       children();
     }
   }
}


[注意: 需要版本 开发快照]

填充操作会从多边形中删除孔,而不改变轮廓。对于凸多边形,结果与 hull() 相同。

示例

示例 1:结果。
// Example 1
 
t = "OpenSCAD";

linear_extrude(15) {
	text(t, 50);
}
color("darkslategray") {
	linear_extrude(2) {
		offset(4) {
			fill() {
				text(t, 50);
			}
		}
	}
}

闵可夫斯基

[编辑 | 编辑源代码]
一个盒子和一个圆柱体
盒子和圆柱体的闵可夫斯基和

显示子节点的 闵可夫斯基和

用法示例

假设你有一个扁平的盒子,你想给它一个圆角。有多种方法可以做到这一点(例如,参见下面的 hull),但闵可夫斯基方法很优雅。取你的盒子和一个圆柱体

 $fn=50;
 cube([10,10,1]);
 cylinder(r=2,h=1);

然后,对它们进行闵可夫斯基和(注意盒子的外尺寸现在是 10+2+2 = 14 个单位乘以 14 个单位乘以 2 个单位高,因为对象的的高度会相加)

$fn=50;
minkowski()
{
  cube([10,10,1]);
  cylinder(r=2,h=1);
}

注意:第二个对象的原点用于加法。以下闵可夫斯基和是不同的:第一个从圆柱体向 -x、+x、-y、+y 方向扩展原始立方体 +1 个单位,从圆柱体向 -z、+z 方向扩展 0.5 个单位。第二个从圆柱体向 -x、+x、-y、+y 和 +z 方向扩展它 +1 个单位,但从圆柱体向 -z 方向扩展 0 个单位。

minkowski() {
	cube([10, 10, 1]);
	cylinder(1, center=true);
}
minkowski() {
	cube([10, 10, 1]);
	cylinder(1);
}

警告: 对于 $fn 的高值,闵可夫斯基和最终可能会消耗大量的 CPU 和内存,因为它必须将每个元素的每个子节点与每个其他元素的所有节点组合。因此,例如,如果 $fn=100 并且你组合了两个圆柱体,那么它不会像两个独立的圆柱体那样只执行 200 个操作,而是执行 100*100 = 10000 个操作。

警告: 如果其中一个输入是复合的,例如

    {
         translate([0, 0, collar])
         sphere(ball);
         cylinder(collar, ball, ball);
    }

它可能会被视为两个单独的输入,从而导致输出过大,并且表面之间具有特征,这些特征应该在彼此之间保持不变。如果是这样,请使用 union()

两个圆柱体
两个圆柱体的凸包

显示子节点的 凸包

用法示例

hull() {
    translate([15,10,0]) circle(10);
    circle(10);
}

二维对象的凸包使用它们在 xy 平面上的投影(阴影),并在 xy 平面生成结果。它们的高度不会在操作中使用。

参考两个圆柱体的凸包的插图,在两个二维圆上使用 hull() 然后 线性拉伸 生成的二维形状以形成三维形状在计算上更有效,而不是在两个圆柱体上使用 hull(),即使结果对象看起来相同。如果可能,通过从二维开始,可以更快地渲染涉及 hull() 的复杂几何形状。

华夏公益教科书