跳转到内容

OpenJSCAD 用户指南

75% developed
来自维基教科书,开放世界中的开放书籍

欢迎使用 OpenJSCAD 用户和编程指南。

OpenJSCAD.org Overview
OpenJSCAD.org 概述

为了提供上下文,OpenJSCAD.org 建立在 OpenJsCad (Github) 之上,它本身受到 OpenSCAD.org 的启发,并且本质上为开发 3D 模型提供了一种程序员方法。 特别是,此增强功能针对为 3D 打印创建精确模型进行了调整。

OpenJSCAD 使用 OpenSCAD 的程序员可能会欢迎

  • 能够使用 JavaScript 编程概念和库
  • 能够创建和操作 3D 形状,以及 2D 形状
  • 支持 OpenSCAD 源代码(大约 80% 的所有函数)
  • 其他功能,以简化向 OpenJSCAD 的过渡


继续阅读以了解有关 OpenJSCAD 的更多信息。

还有一个 快速参考

OpenJSCAD 用户指南

[编辑 | 编辑源代码]

通过 Web 浏览器使用 OpenJSCAD

[编辑 | 编辑源代码]

OpenJSCAD 可以通过访问项目网站 openjscad.xyz 立即使用。

OpenJSCAD 展示了一个页面,该页面显示了一个 3D 视图器以及一个编辑器。

在这里,您可以

  • 使用内置编辑器在线编辑,或
  • 通过您喜欢的编辑器离线编辑

您可以通过将文件或文件夹拖放到指定区域来开始编辑。

为了使用您喜欢的编辑器,请确保选择了自动重新加载。 任何对文件所做的更改将自动重新加载。

注意:每个浏览器(Firefox、Chrome、IE 等)支持略有不同的功能。 如果您遇到问题,请尝试使用其他浏览器。

离线使用 OpenJSCAD

[编辑 | 编辑源代码]

OpenJSCAD 可以通过 GitHub 或 NPM 在本地安装。 然后,您可以通过打开“index.html”将您的浏览器用作本地安装的应用程序。 要查找 index.html 的位置,您可能需要找出 OpenJSCAD 的所在位置。 例如,如果 OpenJSCAD 安装在 /usr/local/lib/node_modules/@jscad/openjscad 中,则

cd /usr/local/lib/node_modules/@jscad/openjscad
open index.html

将启动您的网络浏览器(示例脚本适用于 MacOs)

通过 NPM 进行本地安装

[编辑 | 编辑源代码]

OpenJSCAD 可以使用 节点版本管理器 (NVM) 很容易安装。

  1. 下载并安装 NVM
  2. 安装后,输入“nvm install v6
  3. 然后输入“nvm use v6”

注意:需要 Node.js 的 LTS 版本 > 6.0.0。 我们使用 Node.js 版本 6.x.x 和 7.x.x 测试 OpenJSCAD。

现在 OpenJSCAD 可以通过以下方式下载和安装

npm install -g @jscad/openjscad

通过 GitHub 进行本地安装

[编辑 | 编辑源代码]

OpenJSCAD 也可以从 GitHub 轻松安装。 如果要创建用于在线使用的网站,这是首选的安装方法。

cd base-directory-of-website
git clone https://github.com/jscad/OpenJSCAD.org
cd OpenJSCAD.org

注意:您可能需要进行配置更改以允许访问某些内容(例如示例)。

通过 Web 浏览器

[编辑 | 编辑源代码]

本地安装后,可以通过浏览器打开`index.html`访问 OpenJSCAD。 您可以将文件或文件夹拖放到浏览器中。

注意:Chrome 和其他浏览器在离线时不支持拖放。

您可以拖放任何示例,以及其他设计或文件。

通过命令行

[编辑 | 编辑源代码]
% cd examples
% openjscad logo.jscad
% openjscad logo.jscad -o test.stl
% openjscad logo.jscad -of stl

它创建了 ``logo.stl`` 或 ``test.stl``。

此外,您可以导入 OpenSCAD(.scad)、STL ASCII 或二进制(.stl)和 AMF(.amf)文件,并创建 .jscad、.stl(ASCII 或二进制)、dxf 或 .amf

% openjscad example001.scad -o example001.jscad
% openjscad example001.scad -o example001.stl
% openjscad frog.stl -o frog.jscad
% openjscad frog.stl -o frog2.stl             # does actually stl -> jscad -> stl (ascii)
% openjscad example001.jscad -o example001.amf  
% openjscad example001.jscad -of amf          # creates example001.amf
% openjscad example001.jscad -of stlb         # creates example001.stl (binary)
% openjscad example001.jscad -of stlb -o test.stl
  • -o 代表输出
  • -of 代表输出格式(jscad、stl(默认)、stla、stlb、amf、dxf)

另请参阅如何从 CLI 传递变量到 main()。

支持的语言/文件格式

[编辑 | 编辑源代码]

目前支持以下语言和文件格式

格式 扩展名 网站 备注
JSCAD .jscad openjscad.xyz JSCAD 是一种软件,可以使用您的浏览器创建 3D 实体 CAD 对象。
SCAD .scad OpenSCAD.org OpenSCAD 是一种软件,用于创建 3D 实体 CAD 对象。(仅导入)
STL .stl 维基百科:STL(文件格式) STL 文件仅描述三维对象的表面几何形状
AMF .amf 维基百科:AMF(文件格式) 增材制造文件格式(非常实验性)
DXF .dxf DXF(文件格式) 图形交换文件格式(仅导出)
X3D .x3d Web3D.org 使用 XML 表示 3D 对象的开放标准文件格式。
SVG .svg W3C SVG 标准 可缩放矢量图形格式

当您拖放文件时,语言或格式根据文件扩展名(.jscad 等)设置。 当您开始直接使用浏览器进行编辑时,默认语言为 JSCAD

[编辑 | 编辑源代码]

您可以通过创建包含 OpenJSCAD 和设计的特殊 URL 与他人分享设计。

分享在线设计

[编辑 | 编辑源代码]
  1. http://openjscad.org/#http://openjscad.org/examples/slices/tor.jscad
  2. http://openjscad.org/#http://www.thingiverse.com/download:164128 (STL)
  3. http://openjscad.org/#http://pastebin.com/raw.php?i=5RbzVguT (SCAD)
  4. http://openjscad.org/#http://amf.wikispaces.com/file/view/Rook.amf/268219202/Rook.amf (AMF)


分享本地设计

[编辑 | 编辑源代码]
  1. http://openjscad.org/#examples/slices/tor.jscad
  2. https://127.0.0.1/OpenJSCAD.org/#examples/slices/tor.jscad

OpenJSCAD 编程指南

[编辑 | 编辑源代码]

通常,设计使用 JavaScript 语言编写。您可以在网上找到关于 JavaScript 的培训和帮助。

创建新设计从编写简单的脚本开始,这些脚本调用 CSG 函数和其他特殊函数,如 OpenJSCAD 提供的函数。OpenJSCAD 执行脚本并渲染 3D 设计以供查看。

OpenJSCAD 遵循向函数传递参数的特定标准。但是,大多数参数是可选的,因为提供了默认值。

当需要 3D 向量时,可以将参数作为数组传递。如果将标量(单值)传递给期望 3D 向量的参数,则标量将用于 x、y 和 z 值。换句话说:radius: 1 将给出 radius: [1,1,1]。

需要示例

OpenJSCAD 脚本的结构

[编辑 | 编辑源代码]

OpenJSCAD 脚本必须至少定义一个函数,即 main() 函数,该函数必须返回一个 CSG 对象,或一个不相互交叉的 CSG 对象数组。

function main() {
   return union(sphere(), ...);    // an union of objects or
   return [sphere(), ...];        // an array of non-intersecting objects
}

或者像这样

var w = new Array();
function a() {
   w.push( sphere() );
   w.push( cube().translate([2,0,0]) );
}
function main() {
   a();
   return w;
}

但这起作用。

var w = new Array();
w.push( sphere() );                    // Note: it's not within a function (!!)
w.push( cube().translate([2,0,0]) );

function main() {
    return w;
}

因为所有 CSG 创建(如 3D 原语)都必须在 main() 函数调用的函数内发生。

3D 原语

[编辑 | 编辑源代码]

所有圆形实体都有一个 resolution 参数,它控制细分。如果将 resolution 设置为 8,则每 360 度旋转使用 8 个多边形。注意,增加 resolution 会大大增加渲染时间。对于球体,多边形数量随着使用的 resolution 呈二次方增长。如果省略 resolution 参数,则使用以下两个全局默认值

  • CSG.defaultResolution2D
  • CSG.defaultResolution3D

前者用于 2D 曲线(圆形、圆柱体),后者用于 3D 曲线(球体、3D 扩展)。

类似 OpenSCAD 的函数支持 fn 参数,它是近似球体的段数(默认值为 32,每个球体的总多边形数为 fn*fn)。

立方体

[编辑 | 编辑源代码]

可以像这样创建立方体或盒子

cube(); // openscad like
cube(1);
cube({size: 1});
cube({size: [1,2,3]});
cube({size: 1, center: true}); // default center:false
cube({size: 1, center: [false,false,false]}); // individual axis center true or false
cube({size: [1,2,3], round: true});

CSG.cube(); // using the CSG primitives
CSG.cube({
    center: [0, 0, 0],
    radius: [1, 1, 1]
});

CSG.cube({ // define two opposite corners
    corner1: [4, 4, 4],
    corner2: [5, 4, 2]
});

CSG.roundedCube({ // rounded cube
    center: [0, 0, 0],
    radius: 1,
    roundradius: 0.9,
    resolution: 8,
});

可以像这样创建球体

sphere();                          // openscad like
sphere(1);
sphere({r: 2});                    // Note: center:true is default (unlike other primitives, as OpenSCAD)
sphere({r: 2, center: true});     // Note: OpenSCAD doesn't support center for sphere but we do
sphere({r: 2, center: [false, false, true]}); // individual axis center 
sphere({r: 10, fn: 100 });
sphere({r: 10, fn: 100, type: 'geodesic'});  // geodesic approach (icosahedron further triangulated)

CSG.sphere();                      // using the CSG primitives
CSG.sphere({
  center: [0, 0, 0],
  radius: 2,                      // must be scalar
  resolution: 128
});

如果 ``type: 'geodesic'``,则 fn 会尝试匹配非测地线的 fn,但实际上它以 6 步递增(例如,fn=6..11 是相同的),fn = 1 揭示了基本形式:正二十面体。

注意:创建高分辨率球体,然后对其进行操作(例如,union()、intersection() 等),由于多边形数量巨大,会减慢渲染/构建过程。

圆柱体

[编辑 | 编辑源代码]

可以像这样创建圆柱体和圆锥体

cylinder({r: 1, h: 10});                 // openscad like
cylinder({d: 1, h: 10});
cylinder({r: 1, h: 10, center: true});   // default: center:false
cylinder({r: 1, h: 10, center: [true, true, false]});  // individual x,y,z center flags
cylinder({r: 1, h: 10, round: true});
cylinder({r1: 3, r2: 0, h: 10});
cylinder({d1: 1, d2: 0.5, h: 10});
cylinder({start: [0,0,0], end: [0,0,10], r1: 1, r2: 2, fn: 50});

CSG.cylinder({                      //using the CSG primitives
  start: [0, -1, 0],
  end: [0, 1, 0],
  radius: 1,                        // true cylinder
  resolution: 16
});
CSG.cylinder({
  start: [0, -1, 0],
  end: [0, 1, 0],
  radiusStart: 1,                   // start- and end radius defined, partial cones
  radiusEnd: 2,
  resolution: 16
});
CSG.roundedCylinder({               // and its rounded version
  start: [0, -1, 0],
  end: [0, 1, 0],
  radius: 1,
  resolution: 16
});

其中 fn 是近似圆柱体圆形轮廓的段数(默认值为 32)。

圆环面

[编辑 | 编辑源代码]

圆环面定义如下

  • ri = 内半径(默认值:1),
  • ro = 外半径(默认值:4),
  • fni = 内分辨率(默认值:16),
  • fno = 外分辨率(默认值:32),
  • roti = 内旋转(默认值:0)
torus();                    // ri = 1, ro = 4;  
torus({ ri: 1.5, ro: 3 });
torus({ ri: 0.2 });

torus({ fni:4 });           // make inner circle fn = 4 => square
torus({ fni:4,roti:45 });   // rotate inner circle, so flat is top/bottom
torus({ fni:4,fno:4,roti:45 });
torus({ fni:4,fno:5,roti:45 });

多面体

[编辑 | 编辑源代码]

使用点列表和三角形或多边形列表创建多面体。点列表是形状的所有顶点,三角形列表是点与多面体表面的关系。

polyhedron({      // openscad-like (e.g. pyramid)
  points: [ [10,10,0],[10,-10,0],[-10,-10,0],[-10,10,0], // the four points at base
            [0,0,10] ],                                  // the apex point 
  triangles: [ [0,1,4],[1,2,4],[2,3,4],[3,0,4],          // each triangle side
               [1,0,3],[2,1,3] ]                         // two triangles for square base
});

此外,您还可以定义 `polygons: [ [0,1,4,5], [..] ]`,而不仅仅是 `triangles:`。

您还可以以更低级的级别创建多面体

var polygons = [];
polygons.push(new CSG.Polygon([
      new CSG.Vertex(new CSG.Vector3D(-5,-5,0)),
      new CSG.Vertex(new CSG.Vector3D(2,2,5)),
      new CSG.Vertex(new CSG.Vector3D(3,3,15))
   ])
);
// add more polygons and finally:
solid = CSG.fromPolygons(polygons);

``vector_text(x,y,string)`` 和 ``vector_char(x,y,char)`` 会为您提供以矢量形式渲染的文本或字符的线段。

var l = vector_text(0,0,"Hello World!");   // l contains a list of polylines to be drawn
var o = [];
l.forEach(function(pl) {                   // pl = polyline (not closed)
   o.push(rectangular_extrude(pl, {w: 2, h: 2}));   // extrude it to 3D
});
return union(o);

还支持使用“\n”的多行文本,目前仅支持左对齐。如果您想深入了解细节,可以请求单个字符。

var c = vector_char(x,y,"A");
c.width;    // width of the vector font rendered character
c.segments; // array of segments / polylines

3D 变换

[编辑 | 编辑源代码]
var obj = sphere(5);
scale(2,obj);          // openscad like
scale([1,2,3],obj);    //      '' 

obj.scale([1,2,3]);    // using CSG objects' built in methods
var obj = cube([5,20,5]);
rotate([90,15,30],obj);       // openscad like
rotate(90,[1,0.25,0.5],obj);  //    ''

obj.rotateX(90);              // using CSG objects' built in methods
obj.rotateY(45);
obj.rotateZ(30);

obj.rotate(rotationCenter, rotationAxis, degrees)
obj.rotateEulerAngles(alpha, beta, gamma, position)
translate([0,0,10],obj);  // openscad like

obj.translate([0,0,10]);  // using CSG objects' built in methods

将对象整体或轴向居中

center(true,cube());                // openscad-like all axis
center([true,true,false],cube());   // openscad-like axis-wise [x,y]

// false = do nothing, true = center axis

cube().center();                // using CSG objects' built in methods
cube().center('x','y');         // using CSG objects' built in method to center axis-wise [x,y]

center() 和 .center() 可以帮助您组合一个对称的,在组合时(例如,从参数化设计)您不知道其完整尺寸的形状。

矩阵操作

[编辑 | 编辑源代码]
var m = new CSG.Matrix4x4();
m = m.multiply(CSG.Matrix4x4.rotationX(40));
m = m.multiply(CSG.Matrix4x4.rotationZ(40));
m = m.multiply(CSG.Matrix4x4.translation([-.5, 0, 0]));
m = m.multiply(CSG.Matrix4x4.scaling([1.1, 1.2, 1.3]));

// and apply the transform:
var cube3 = cube().transform(m);
mirror([10,20,90], cube(1)); // openscad like

var cube = CSG.cube().translate([1,0,0]);   // built in method chaining

var cube2 = cube.mirroredX(); // mirrored in the x=0 plane
var cube3 = cube.mirroredY(); // mirrored in the y=0 plane
var cube4 = cube.mirroredZ(); // mirrored in the z=0 plane

// create a plane by specifying 3 points:
var plane = CSG.Plane.fromPoints([5,0,0], [5, 1, 0], [3, 1, 7]);

// and mirror in that plane:
var cube5 = cube.mirrored(plane);
union(sphere({r: 1, center:true}),cube({size: 1.5, center:true}));  // openscad like

可以添加多个对象,也可以添加数组。

sphere({r: 1, center:true}).union(cube({size: 1.5, center:true}));  // using CSG objects' built in methods
intersection(sphere({r: 1, center:true}),cube({size: 1.5, center:true})); // openscad like

可以将多个对象进行交集,也可以添加数组。

sphere({r: 1, center:true}).intersect(cube({size: 1.5, center:true}));   // using CSG objects' built in methods

注意 intersection()(类似 openscad)与 intersect()(函数与 CSG 对象内置方法)之间的区别。

差集 (减法)

[编辑 | 编辑源代码]
difference(sphere({r: 1, center:true}),cube({size: 1.5, center:true}));    // openscad like

可以将多个对象从第一个元素中进行差集(减去),也可以添加数组。

sphere({r: 1, center:true}).subtract(cube({size: 1.5, center:true}));      // using CSG objects' built in methods

注意:difference()(类似 openscad)与 subtract()(方法,面向对象)之间的区别。

二维基元

[编辑 | 编辑源代码]
circle();                        // openscad like
circle(1); 
circle({r: 2, fn:5});            // fn = number of segments to approximate the circle
circle({r: 3, center: true});    // center: false (default)

CAG.circle({center: [0,0], radius: 3, resolution: 32});   // using CSG objects' built in methods

正方形 / 矩形

[编辑 | 编辑源代码]
square();                                   // openscad like
square(1);                                  // 1x1
square([2,3]);                              // 2x3
square({size: [2,4], center: true});        // 2x4, center: false (default)

CAG.rectangle({center: [0,0], radius: [w/2, h/2]});   // CAG built ins, where w or h = side-length of square
CAG.roundedRectangle({center: [0,0], radius: [w/2, h/2], roundradius: 1, resolution: 4});

多边形

[编辑 | 编辑源代码]
polygon([ [0,0],[3,0],[3,3] ]);                // openscad like
polygon({ points: [ [0,0],[3,0],[3,3] ] });                    
polygon({ points: [ [0,0],[3,0],[3,3],[0,6] ], paths: [ [0,1,2],[1,2,3] ] }); // multiple paths not yet implemented

var shape1 = CAG.fromPoints([ [0,0],[5,0],[3,5],[0,5] ]);    // CAG built ins

二维变换

[编辑 | 编辑源代码]
translate([2,2], circle(1));      // openscad like
rotate([0,0,90], square());       //     ''
shape = center(true, shape());    // center both axis
shape = center([true,false], shape()); // center axis-wise [x] 

shape = shape.translate([-2, -2]);   // object methods
shape = shape.rotateZ(20);
shape = shape.scale([0.7, 0.9]);
shape = shape.center();          // center both axis
scape = shape.center('x');       // center axis-wise [x]

二维路径

[编辑 | 编辑源代码]

路径只是一系列点,由线连接。路径可以是开放的或封闭的(在第一个点和最后一个点之间绘制一条额外的线)。二维路径通过 CSG.Path2D 类得到支持。二维路径与二维 CAG 之间的区别在于,路径是一条“细”线,而 CAG 是一个封闭区域。

路径可以通过向构造函数提供二维坐标数组或通过各种 CSG.Path2D 成员函数来构建,这些成员函数包括

  • arc(endpoint, options):返回一条圆形或椭圆曲线路径(有关用法,请参见下面的示例)。
  • appendPoint([x,y]):创建并返回一个新的 Path2D,其中包含调用者的点,后跟给定点。
  • appendPoints([[x,y],...]):创建并返回一个新的 Path2D,其中包含调用者的点,后跟给定的点。[注意:截至 2016 年 8 月 13 日,此方法还会修改调用者;这可能是错误,将来可能会更改;请参阅问题:165]
  • appendBezier([[x,y],...], options):创建并返回一个新的 Path2D,其中包含调用者的点,后跟一条以给定最后一个点结束的贝塞尔曲线;所有除最后一个点之外的给定点都是贝塞尔的控制点;一个空初始控制点意味着使用调用者的最后两个点作为新贝塞尔曲线的控制点。选项可以指定 {resolution: <NN>}。

可以使用 .concat() 连接路径,结果是新的路径。

路径可以通过两种方式转换为 CAG

  • expandToCAG(pathradius, resolution) 用一个圆跟踪路径,实际上使路径的线段变粗。
  • innerToCAG() 创建一个由路径包围的 CAG。路径应为封闭路径。

目前,rectangularExtrude() 函数支持创建三维实体。这通过用二维矩形(直立,垂直于路径方向)跟踪路径来创建一个三维形状

var path = new CSG.Path2D([ [10,10], [-10,10] ], /* closed = */ false);
var anotherpath = new CSG.Path2D([ [-10,-10] ]);
path = path.concat(anotherpath);
path = path.appendPoint([10,-10]);
path = path.close(); // close the path

// of course we could simply have done:
// var path = new CSG.Path2D([ [10,10], [-10,10], [-10,-10], [10,-10] ], /* closed = */ true);

// We can make arcs and circles:
var curvedpath = CSG.Path2D.arc({
  center: [0,0,0],
  radius: 10,
  startangle: 0,
  endangle: 180,
  resolution: 16,
});

您可以将多个二维多边形(例如 circle()、square()、polygon())一起进行凸包运算。

var h = hull( square(10),circle(10).translate([10,10,0]) );

linear_extrude({ height: 10 }, h);

链式凸包

[编辑 | 编辑源代码]

链式凸包是针对多个二维形状进行的凸包的一种变体,本质上是对多个形状进行顺序凸包运算,然后将这些凸包进行并集,基于 Whosa whatsis 的想法。

chain_hull( 
    circle(), circle().translate([2,0,0]), ... );   // list of CAG/2D forms

var a = [];
a.push(circle()); 
chain_hull( a );                       // array of CAG/2D forms

chain_hull({closed: true},             // default is false
   [circle(),circle().translate([2,0,0]),circle().translate([2,2,0])]);
   // notice that with parameter {closed:true}, hull_chain requires an array

拉伸 / 拉伸

[编辑 | 编辑源代码]

线性拉伸

[编辑 | 编辑源代码]

将二维形状拉伸成三维形状,给定高度、扭曲(度数)和切片数(如果进行扭曲)。

// openscad like
linear_extrude({ height: 10 }, square());
linear_extrude({ height: 10, twist: 90 }, square([1,2]));
linear_extrude({ height: 10, twist: 360, slices: 50}, circle().translate([1,0,0]) );

linear_extrude({ height: 10, center: true, twist: 360, slices: 50}, translate([2,0,0], square([1,2])) );
linear_extrude({ height: 10, center: true, twist: 360, slices: 50}, square([1,2]).translate([2,0,0]) );

二维形状的线性拉伸,可以选择扭曲。二维形状放置在 z=0 平面,并沿 <offset>(CSG.Vector3D)方向拉伸。最终面旋转 <twistangle> 度。旋转围绕二维形状的原点(即 x=0,y=0)进行,twiststeps 决定扭曲的分辨率(应大于等于 1),返回一个 CSG 对象。

// CAG build in method
var c = CAG.circle({radius: 3});
extruded = c.extrude({offset: [0,0,10], twistangle: 360, twiststeps: 100});

矩形拉伸

[编辑 | 编辑源代码]

通过用矩形(直立,垂直于路径方向)跟踪路径来拉伸路径,返回一个 CSG 实体。

简化版(类似 openscad,即使 OpenSCAD 没有提供此功能),通过 rectangular_extrude(),其中

  • w:宽度(默认值:1),
  • h:高度(默认值:1),
  • fn:分辨率(默认值:8),以及
  • closed:路径是否封闭(默认值:false)
rectangular_extrude([ [10,10], [-10,10], [-20,0], [-10,-10], [10,-10] ],  // path is an array of 2d coords
    {w: 1, h: 3, closed: true});

或者更低级的 rectangularExtrude(),使用以下未命名的变量

  1. 拉伸的宽度,在 z=0 平面
  2. 拉伸的高度,在 z 方向
  3. 分辨率,角落曲线的每个 360 度的片段数
  4. roundEnds:如果为真,则多边形的端点将被圆化,否则它们将是平的
// first creating a 2D path, and then extrude it
var path = new CSG.Path2D([ [10,10], [-10,10], [-20,0], [-10,-10], [10,-10] ], /*closed=*/true);
var csg = path.rectangularExtrude(3, 4, 16, true);   // w, h, resolution, roundEnds
return csg;

旋转拉伸

[编辑 | 编辑源代码]

此外,还可以使用 rotate_extrude()

// openscad-like
rotate_extrude( translate([4,0,0], circle({r: 1, fn: 30, center: true}) ) );

// using CSG objects' built in methods to translate 
rotate_extrude({fn:4}, square({size: [1,1], center: true}).translate([4,0,0]) );

rotate_extrude( polygon({points:[ [0,0],[2,1],[1,2],[1,3],[3,4],[0,5] ]}) );
rotate_extrude({fn:4}, polygon({points:[ [0,0],[2,1],[1,2],[1,3],[3,4],[0,5] ]}) );

您基本上可以拉伸任何二维多边形(圆形、正方形或多边形)。

实体的“property”属性可用于存储对象的元数据,例如实体某个特定兴趣点的坐标。每当对象被变换(即旋转、缩放或平移)时,属性也会随之变换。因此,即使对实体应用了多个变换,属性也会继续指向相同的兴趣点。

属性可以是任何类型,但只有支持“transform”方法的类的属性才会被实际变换。这包括 CSG.Vector3D、CSG.Plane 和 CSG.Connector。特别是 CSG.Connector 属性(见下文)非常有用:它们可以用来将实体连接到另一个实体的预定位置,无论当前方向如何。

甚至可以将 CSG 实体作为另一个实体的属性。例如,这可以用于定义用于创建与对象匹配的螺钉孔的切口圆柱体。这些“实体属性”会获得与拥有实体相同的变换,但在 union() 等 CSG 操作的结果中将不可见。

其他类型的属性(例如,字符串)将仍然包含在变换后的实体的属性中,但当拥有实体被变换时,属性不会获得任何变换。

所有基元实体都有一些预定义的属性,例如球体的中心点(TODO:文档化)。

由 CSG 操作(union()、subtract()、intersect())产生的实体将获得两个源实体的合并属性。如果存在同名属性,则只保留其中一个。

var cube = CSG.cube({radius: 1.0});
cube.properties.aCorner = new CSG.Vector3D([1, 1, 1]);
cube = cube.translate([5, 0, 0]);
cube = cube.scale(2);
// cube.properties.aCorner will now point to [12, 2, 2],
// which is still the same corner point 

// Properties can be stored in arrays; all properties in the array
// will be transformed if the solid is transformed:
cube.properties.otherCorners = [
  new CSG.Vector3D([-1, 1, 1]),
  new CSG.Vector3D([-1, -1, 1])
];

// and we can create sub-property objects; these must be of the 
// CSG.Properties class. All sub properties will be transformed with
// the solid:
cube.properties.myProperties = new CSG.Properties();
cube.properties.myProperties.someProperty = new CSG.Vector3D([-1, -1, -1]);

连接器

[编辑 | 编辑源代码]

CSG.Connector 类旨在简化将两个实体在预先确定的位置和方向上连接在一起的操作。例如,假设我们有一个表示伺服电机的 CSG 实体和一个表示伺服臂的实体:通过为它们中的每一个定义一个 Connector 属性,我们可以轻松地将伺服臂连接到伺服电机在正确的位置(即电机轴)和方向(即臂垂直于轴)上,即使我们不知道它们在 3D 空间中的当前位置和方向。

换句话说,Connector 使我们能够自由地旋转和平移物体,而无需跟踪它们的位置和边界。如果第三方库为其实体公开连接器,则库的用户无需了解实际尺寸或形状,只需要知道连接器属性的名称。

CSG.Connector 由 3 个属性组成

  • point:一个 CSG.Vector3D,定义了 3D 空间中的连接点
  • axis:一个 CSG.Vector3D,定义了连接的方向向量(在伺服电机示例中,它将指向轴的方向)
  • normal:一个 CSG.Vector3D 方向向量,与轴大致垂直;这定义了连接的“12 点钟”方向。

连接两个连接器时,实体将进行变换,使得 point 属性将相同,axis 属性将具有相同的方向(如果 mirror == true,则为相反方向),并且 normal 尽可能匹配。

连接器可以通过两种方法连接:CSG 实体的 connectTo() 函数将变换实体,使得两个连接器连接起来。或者,我们可以使用连接器的 getTransformationTo() 方法来获取一个变换矩阵,该矩阵将连接连接器。如果需要对多个实体应用相同的变换,可以使用这种方法。

var cube1 = CSG.cube({radius: 10});
var cube2 = CSG.cube({radius: 4});

// define a connector on the center of one face of cube1
// The connector's axis points outwards and its normal points
// towards the positive z axis:
cube1.properties.myConnector = new CSG.Connector([10, 0, 0], [1, 0, 0], [0, 0, 1]);

// define a similar connector for cube 2:
cube2.properties.myConnector = new CSG.Connector([0, -4, 0], [0, -1, 0], [0, 0, 1]);

// do some random transformations on cube 1:
cube1 = cube1.rotateX(30);
cube1 = cube1.translate([3.1, 2, 0]);

// Now attach cube2 to cube 1:
cube2 = cube2.connectTo(
  cube2.properties.myConnector, 
  cube1.properties.myConnector, 
  true,   // mirror 
  0       // normalrotation
);

// Or alternatively:
var matrix = cube2.properties.myConnector.getTransformationTo(
  cube1.properties.myConnector, 
  true,   // mirror 
  0       // normalrotation
);
cube2 = cube2.transform(matrix);

var result = cube2.union(cube1);

边界和表面铺设

[编辑 | 编辑源代码]

getBounds() 函数可以用来检索对象的边界框,返回一个包含两个 CSG.Vector3Ds 的数组,指定最小 X、Y、Z 坐标和最大 X、Y、Z 坐标。

lieFlat() 函数将物体铺设在 Z 表面上,使得 Z 高度最小化,并且物体围绕 Z 轴居中。这对于 CNC 铣削非常有用,因为它允许在铣削过程中将物体变换到坯料材料的空间中。或者对于 3D 打印:它以一种可以以最少的层数打印的方式铺设。除了 lieFlat() 函数外,还可以使用 getTransformationToFlatLying() 函数,该函数返回一个 CSG.Matrix4x4 来进行变换。

var cube1 = CSG.cube({radius: 10});
var cube2 = CSG.cube({radius: 5});

// get the right bound of cube1 and the left bound of cube2:
var deltax = cube1.getBounds()[1].x - cube2.getBounds()[0].x;

// align cube2 so it touches cube1:
cube2  = cube2.translate([deltax, 0, 0]);

var cube3 = CSG.cube({radius: [100,120,10]});
// do some random transformations:
cube3 = cube3.rotateZ(31).rotateX(50).translate([30,50,20]);
// now place onto the z=0 plane:
cube3  = cube3.lieFlat();

// or instead we could have used:
var transformation = cube3.getTransformationToFlatLying();
cube3 = cube3.transform(transformation);

return cube3;

OpenSCAD 风格

color([r,g,b], object, object2 ...); // for example, color([1,1,0],sphere());
color([r,g,b], array);
color([r,g,b,a], object, object2 ...);
color([r,g,b,a], array);
color(name, object, object2 ...); // for example, color('red',sphere());
color(name, a, object, object2 ...); // for example, color('red',0.5, sphere());
color(name, array);
color(name, a, array);

命名的颜色不区分大小写,例如,'RED' 与 'red' 相同。

使用 CSG 对象的内置方法(r、g、b 必须在 0 到 1 之间,而不是 0 到 255)

object.setColor([r,g,b]);
object.setColor([r,g,b,a]);
object.setColor(r,g,b);
object.setColor(r,g,b,a);
object.setColor(css2rgb('dodgerblue'));

示例

color([1,0.5,0.3],sphere(1));                      // openscad like
color([1,0.5,0.3],sphere(1),cube(2));
color("Red",sphere(),cube().translate([2,0,0]));   // named color (case-insensitive)

sphere().setColor(1,0.5,0.3);                      // built in methods
sphere().setColor([1,0.5,0.3]);

有关所有可用颜色的信息,请参见 扩展颜色关键字

代码摘录

o.push( color([1,0,0],sphere()) );
o.push( color([0,1,0],cube()) );
o.push( color([0,0,1],cylinder()) );

o.push( color("red",sphere()) );
o.push( color("green", cube()) );
o.push( color("blue", cylinder()) );

for(var i=0; i<1; i+=1/12) {
   o.push( cube().setColor(hsl2rgb(i,1,0.5)) );
}

代码

function main() {
   var o = [];
   for(var i=0; i<8; i++) {
      o.push(cylinder({r:3,h:20}).
         setColor(
            hsl2rgb(i/8,1,0.5).  // hsl to rgb, creating rainbow [r,g,b]
            concat(1/8+i/8)      // and add to alpha to make it [r,g,b,a]
         ).translate([(i-3)*7.5,0,0])
      );
   }
   o.push(color("red",cube(5)).translate([-4,-10,0]));
   o.push(color("red",0.5,cube(5)).translate([4,-10,0]));
   return o;
}

注意:有一些 OpenGL 透明度限制,例如,根据颜色的顺序,你可能无法透过部分透明的物体看到。

颜色空间转换

[编辑 | 编辑源代码]

以下函数用于在颜色空间之间转换

var hsl = rgb2hsl(r,g,b); // or rgb2hsl([r,g,b]);
var rgb = hsl2rgb(h,s,l); // or hsl2rgb([h,s,l]);
var hsv = rgb2hsv(r,g,b); // or rgb2hsv([r,g,b]);
var rgb = hsv2rgb(h,s,v); // or hsv2rgb([h,s,v]);

其中

  • r、g、b(红色、绿色、蓝色)
  • h、s、l(色调、饱和度、亮度)
  • h、s、v(色调、饱和度、值)

例如,要创建彩虹,t = 0..1 并且 .setColor(hsl2rgb(t,1,0.5))

有关示例,请参见 Tor(多色)

a = 1, b = 2;
echo("a="+a,"b="+b);

在 JavaScript 控制台中打印:a=1, b=2

数学函数

[编辑 | 编辑源代码]

Javascript 通过 Math 库 提供了一些函数。此外,还提供以下与 OpenSCAD 兼容的函数

sin(a);                   // a = 0..360
cos(a);                   //     ''
asin(a);                  // a = 0..1, returns 0..360
acos(a);                  //       ''
tan(a);                   // a = 0..360
atan(a);                  // a = 0..1, returns 0..360
atan2(a,b);               // returns 0..360
ceil(a);
floor(a);
abs(a);
min(a,b);
max(a,b);
rands(min,max,vn,seed);   // returns random vectors of vn dimension, seed not yet implemented
log(a);
lookup(ix,v);             // ix = index, e.g. v = [ [0,100], [10,10], [20,200] ] whereas v[x][0] = index, v[x][1] = value
                          //    return will be linear interpolated (e.g. lookup(5,[ [0,100], [10,10], [20,200] ]) == 45

pow(a,b);
sign(a);                  // -1, 0 or 1
sqrt(a);
round(a);

直接导入 OpenSCAD 源代码

[编辑 | 编辑源代码]

包含一个 OpenSCAD 到 OpenJSCAD 的转换器,但以下功能尚不可用

  • DXF 导入和操作(例如 import_dxf、dxf-cross、dxf_dim 函数)。
  • rotate_extrude()(注意:OpenJSCAD 支持 rotate_extrude())
  • minkowski() 和 hull() 变换(注意:OpenJSCAD 支持 hull())
  • 全局变量,如 $fa、$fs
  • 修饰符字符:#、 !、 %
  • 列表推导,例如:list = [ for (i = [2, 3, 5, 7, 11]) i * i ];

你可以在内置编辑器中编辑 OpenSCAD 源代码,只要确保第一行是

//!OpenSCAD

然后源代码将以 OpenSCAD 语法显示。

将来可能会提供其他 CAD 语言支持。

将 OpenSCAD 转换为 OpenJSCAD

[编辑 | 编辑源代码]

为了将你的 OpenSCAD 转换为原生 OpenJSCAD 代码,请考虑以下对比。

OpenSCAD

union() {
      //cube(size=[30,30,0.1],center=true);
      translate([3,0,0]) cube();
      difference() {
         rotate([0,-45,0]) cube(size=[8,7,3],center=true);
         sphere(r=3,$fn=20,center=true);
      }
      translate([10,5,5]) scale([0.5,1,2]) sphere(r=5,$fn=50);
      translate([-15,0,0]) cylinder(r1=2,r2=0,h=10,$fn=20);
     
   for(i=[0:19]) {
      rotate([0,i/20*360,0]) 
      translate([i,0,0]) 
      rotate([0,i/20*90,i/20*90,0]) 
      cube(size=[1,1.2,.5],center=true);
   }
}

OpenJSCAD

function main() {  
   var cubes = new Array();
   for(i=0; i<20; i++) {
      cubes[i] = rotate([0,i/20*360,0], 
         translate([i,0,0], 
         rotate([0,i/20*90,i/20*90,0], 
         cube({size:[1,1.2,.5],center:true}))));
   }
   return union(
      //cube({size:[30,30,0.1],center:true}),
      translate([3,0,0],cube()),
      difference(
         rotate([0,-45,0], cube({size:[8,7,3],center:true})),
         sphere({r:3,fn:20,center:true})
      ),
      translate([10,5,5], scale([0.5,1,2], sphere({r:5,fn:50}))),
      translate([-15,0,0], cylinder({r1:2,r2:0,h:10,fn:20})),
      cubes
   );
}

基本上,只要 OpenSCAD 中出现命名参数 func(a=1),就将其转换为 func({a:1}),例如

// OpenSCAD
translate([0,0,2]) sphere(size=2,$fn=50)
// becomes OpenJSCAD
translate([0,0,2], sphere({size:2,fn:50}));
// or
sphere({size:2,fn:50}).translate([0,0,2]);

交互式参数模型

[编辑 | 编辑源代码]

模型可以具有交互式参数,允许用户通过熟悉的表单更改值,即输入数字、滑动条、下拉菜单等。这允许用户更改值并创建任意数量的可能组合,从而使模型在本质上变得动态。可以创建任意数量的自定义设计,然后可以以任何支持的格式下载。

交互式参数可以通过添加一个名为 getParameterDefinitions() 的特定函数来实现。该函数可以添加到 JSCAD 脚本中的任何位置,但必须返回一个参数定义数组。

function getParameterDefinitions() {
  return [{ name: 'width', type: 'float', initial: 10, caption: "Width of the cube:" }];
}

参数定义用于创建一个字段集,用户可以更改这些字段,即选项。字段的值将提供给 JSCAD 脚本的 main() 函数。例如,'width' 参数的值将作为 'params.width' 属性提供,依此类推。

function main(params) {
  // custom error checking:
  if(params.width <= 0) throw new Error("Width should be positive!");
  var mycube = CSG.cube({radius: params.width});
  return mycube();
}

所有常见的 HTML5 字段类型都可用作交互式参数。这包括复选框(布尔值)、颜色、日期、电子邮件、浮点数、整数、数字、密码、滑块、文本和 URL。以及两种用于下拉选择和分组参数的特殊参数类型。

最小参数规范仅包含 'name' 和 'type'。但是,完整的参数规范应具有 'caption' 和 'initial' 值。此外,还有 'min'、'max'、'step'、'checked'、'size'、'maxlength' 和 'placeholder',它们与特定参数类型相关。只要不断尝试不同的组合以获得良好的参数规范。这是一个很好的例子。

{
  name: 'width',
  type: 'float',
  initial: 1.5,
  caption: 'Width of the thingy:',
  min: 1.0,
  max: 5.0,
  step: 0.5
}

此外,还有 'choice' 类型,它为用户创建下拉列表。选择通过指定 'values' 和 'captions' 来提供。选择的值将传递到模型的 main() 函数中。

{
  name: 'shape',
  type: 'choice',
  values: ["TRI", "SQU", "CIR"],               // these are the values that will be supplied to your script
  captions: ["Triangle", "Square", "Circle"],  // optional, these values are shown in the listbox
                                               // if omitted, the items in the 'values' array are used
  caption: 'Shape:',                           // optional, displayed left of the input field
  initial: "SQU",                              // optional, default selected value
                                               // if omitted, the first item is selected by default
                                               // NOTE: parameter "default" is deprecated
}

一个完整的示例

function getParameterDefinitions() {
  return [
    { name: 'width', type: 'float', initial: 10, caption: "Width of the cube:" },
    { name: 'height', type: 'float', initial: 14, caption: "Height of the cube:" },
    { name: 'depth', type: 'float', initial: 7, caption: "Depth of the cube:" },
    { name: 'rounded', type: 'choice', caption: 'Round the corners?', values: [0, 1], captions: ["No thanks", "Yes please"], initial: 1 }
  ];
}

function main(params) {
  var result;
  if(params.rounded == 1) {
    result = CSG.roundedCube({radius: [params.width, params.height, params.depth], roundradius: 2, resolution: 32});
  } else {
    result = CSG.cube({radius: [params.width, params.height, params.depth]});
  }
  return result;
}

openjscad.xyz 上,有很多关于“交互式”参数的示例。有关可用参数类型和浏览器支持的更多信息,请参见快速参考。

通过命令行界面使用参数

[编辑 | 编辑源代码]

命令行界面 ``openjscad`` 可以为交互式设计传递参数。通过以下任一方式

 key value

 key=value

例如

% openjscad name_plate.jscad --name "Just Me" --title "Geek" -o JustMe.amf
% openjscad name_plate.jscad "--name=Just Me" "--title=Geek" -o JustMe.amf

维护较大的项目

[编辑 | 编辑源代码]

包含文件

[编辑 | 编辑源代码]

在使用 OpenJSCAD 创建了一些设计之后,一些通用的函数和部件会变得很有用。include() 函数允许一个 OpenJSCAD 脚本包含另一个 OpenJSCAD 脚本。

简单示例

[编辑 | 编辑源代码]

OpenJSCAD 包含示例球体 另请参阅

// main.jscad
include("lib.jscad");

function main() {
  myLib();
  return myLib.b(2);
}

以及

// lib.jscad
myLib = function() {
   var a = function(n) {  // internal 
      return n*4;  
   }
   myLib.b = function(n) {      // public 
      return sphere(a(n));  
   }
}

注意:主文件必须包含调用:myLib()

面向对象示例

[编辑 | 编辑源代码]

一个遥控器支架的设计,使用了一个名为 “Box” 的类,它从 “Box.jscad” 文件中包含进来。另请参阅 https://github.com/BITPlan/docker-openjscad/tree/master/workspace/RCHolder OpenJSCAD 渲染的遥控器支架设计图片

main.jscad
[编辑 | 编辑源代码]
// title      : Remote Control Holder Test
// author     : Wolfgang Fahl
// license    : Apache License
// revision   : 0.0.1
// tags       : Cube
// file       : RCHolder/main.jscad
include ("Box.jscad");

//
function main() {
  BoxFactory();
  width = 55;
  height = 45;
  len = 30;
  wall = 1.5;
  var boxes = [];
  box=BoxFactory.create(width, len, height, wall, false);
  boxo= BoxFactory.create(width,len,height,wall,false);

  x0=-width*1.5;
  y0=-95
  box.at(x0, y0, 0);
  var ls = [30, 25, 25, 20, 20, 25];
  i=0;
  x=0;
  ls.forEach(function(length) {
    box.length=length;
    if (++i>3) {
      box.x=x0;
      box.y=y0+len-wall;
      i=0;
    }
    boxo.x=box.x;
    boxo.y=box.y;
    boxo.z=box.z;
    boxes.push(box.box());
    boxes.push(boxo.box());
    box.move(width-wall,0,0);
  });
  return union(boxes);
}
Box.jscad
[编辑 | 编辑源代码]
// title      : Box Test
// author     : Wolfgang Fahl
// license    : Apache License
// revision   : 0.0.1
// tags       : Cube
// file       : Box.jscad
class Box {
  constructor(width, length, height, wall, center) {
    this.width = width;
    this.length = length;
    this.height = height;
    this.wall = wall;
    this.center = center;
    this.x = 0;
    this.y = 0;
    this.z = 0;
  }

  /**
   *  create a box
   */
  box() {
    return difference(
      cube({
        size: [this.width, this.length, this.height],
        center: this.center
      }),
      cube({
        size: [this.width - this.wall * 2, this.length - this.wall * 2, this.height - this.wall],
        center: this.center
      }).translate([this.wall, this.wall, this.wall])
    ).translate([this.x, this.y, this.z])
  }

  at(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
  }

  move(x, y, z) {
    this.at(this.x + x, this.y + y, this.z + z);
  }
}

BoxFactory=function () {
   BoxFactory.create=function(pWidth, pLength, pHeight, pWall, pCenter) {
     return new Box(pWidth,pLength,pHeight,pWall,pCenter);
   }
}

柏拉图立体示例

[编辑 | 编辑源代码]

OpenJSCAD 包含示例柏拉图立体设计图片 参见 柏拉图立体示例,它使用了递归的 include()。不过,这是一个不太好的例子,因为它没有对函数名进行本地化。一个清晰的写作风格指南将会展示一个 OpenJSCAD 库应该是什么样子的。

include() 的支持

[编辑 | 编辑源代码]

include() 函数支持

  • 网络在线远程(例如 https://openjscad.xyz/):前提是您拖放了文件,或者它们在网络服务器上可用(例如示例)
  • 网络在线本地(例如 https://127.0.0.1/OpenJSCAD/):前提是您拖放了文件,或者它们在本地网络服务器上可用
  • 网络离线本地(例如 file://..../OpenJSCAD/index.html):前提是您拖放了文件
  • 命令行界面(CLI):前提是它们在本地文件系统中可用

拖放文件设置示例

JSCAD 项目文件布局

[编辑 | 编辑源代码]

假设您要创建一个大型 OpenJSCAD 项目,您可以使用 include() 来分割功能

ProjectName/
   main.jscad          # this one contains the "function main()", this file will be <b>executed</b>
   addon.jscad         # this file could be include("addon.jscad") in main.jscad
   optimizer.jscad     #             ''     include("optimizer.jscad") in main.jscad or also in addon.jscad 
   Makefile            # possible Makefile to do the same on CLI

注意:名为 main.jscad 的文件必须存在,并且必须包含 “function main()” 的声明。

使用多个 JSCAD 文件进行开发

[编辑 | 编辑源代码]

取决于您的浏览器和本地设置,以下内容适用

  • Chrome(版本 26)
* Online (http://...): drag & drop entire folder, e.g. ProjectName/ to the drag & drop zone
* Offline (file://...): drag & drop all jscad files (but not folder) to the drag & drop zone
  • Firefox(版本 19+):将项目的所有 jscad 文件拖放到拖放区域
  • Opera:尚不支持(WebGL 支持尚未可用)
  • IE10:尚不支持(WebGL 支持尚未可用)
华夏公益教科书