User Tools


Design Guide

Creating a new JSCAD design starts by writing simple scripts which call functions to create and manipulate shapes. In general, JSCAD designs are written using the JavaScript language.

Find out more about JavaScript at w3schools

The JSCAD suite of applications executes the script, generates shapes, applies transforms, performs operations, and renders the design for viewing.

Anatomy of a Design

A JSCAD script must have at least one function defined, the main() function, which must to return a shape.

function main() {
  return sphere() // a single shape
}

Or an array of shapes.

function main() {
  const a = cube()
  const b = sphere()
  const c = cylinder()
  return [a,b,c] // an array of shapes
}

In addition, functions can be created and called, i.e. normal JavaScript.

function a(options) { // passed from main() below
  var w = []
  w.push( sphere() )
  w.push( cube(options).translate([2,0,0]) )
  return w
}
function main() {
  let list = a({radius: 10})
  return list
}

Parameter Passing

JSCAD designs can pass parameters from one function to another, just like in the example. This is because JSCAD designs are really JavaScript.

There are a few special parameters which are important to understand.

Passing Options

JSCAD tries to maintain a consistent and easy to use set of functions (API). Although most functions require specific options, most have defaults and do not need to be supplied. Every function has predefined defaults, even shapes (The defaults are shown along side of examples for each function.)

Options are passed as attributes of another object. In most cases, the options are assigned a value, and bracketed with ‘{…}’.

  cylinder({start: [0,0,0], end: [0,0,10], r1: 1, r2: 2, fn: 50})

Why the strange syntax? There can be lots parameters, default parameters can be skipped, order is not important, etc. This provides a lot of flexibility when creating complex designs.

Passing Vectors

When 3D vectors are required, parameters can be passed as an array. If a scalar (single value) is passed for a parameter which expects a 3D vector, the scalar is used for the x, y and z values. In other words: radius: 1 will give radius: [1,1,1].

Design Parameters

A design can have parameters by declaring a special function; getParameterDefinitions().

In applications and browsers, these parameters are presented to users, allowing users to interactively change designs.

Usage

This function must return an array of parameter definitions, as show below.

function getParameterDefinitions() {
    return [
        { name: 'length', type: 'int', initial: 150, caption: 'Length?' }, 
        { name: 'width', type: 'int', initial: 100, caption: 'Width?' },
    ];
}

The parameters are evaluated and values are passed into the main function. Be sure to declare the main function properly.

function main(params) {
  var l = params.length;
  var w = params.width;
...
}

Parameter Types

The parameters are defined as input fields on a single HTML5 form, i.e. the list of parameters. For more information on HTML5 input fields, see some examples at W3 Schools.

Note: Browsers are NOT the same and will treat unsupported parameter types as TEXT.

Type Example Returned Value
checkbox {name: 'bigorsmall', type: 'checkbox', checked: true, caption: 'Big?'} if checked true, else false
checkbox {name: 'bigorsmall', type: 'checkbox', checked: true, initial: 20, caption: 'Big?'} if checked 20, else false
color { name: 'color', type: 'color', initial: '#FFB431', caption: 'Color?' } “#rrggbb”, use html2rgb() to convert
date {name: 'birthday', type: 'date', caption: 'Birthday?'} “YYYY-MM-DD”
email {name: 'address', type: 'email', caption: 'Email Address?'} string value
float {name: 'angle', type: 'number', initial: 2.5, step: 0.5, caption: 'Angle?'} float value
int {name: 'age', type: 'int', initial: 20, caption: 'Age?'} integer value
number {name: 'angle', type: 'number', initial: 2.5, step: 0.5, caption: 'Angle?'} float value
password {name: 'password', type: 'password', caption: 'Secret?'} string value
slider {name: 'count', type: 'slider', min: 2, max: 10, caption: 'How many?'} float value
text {name: 'name', type: 'text', caption: 'Name?'} string value
url {name: 'webpage', type: 'url', caption: 'Web page URL?'} string value
group { name: 'balloon', type: 'group', caption: 'Balloons' } none, only displayed

Note: The parameters accept additional restrictions and assistance. These include 'initial', 'max', 'maxLength', 'min', 'pattern', 'placeholder', 'size', and 'step'.

3D Primitives

‘3D’ stands for three (3) dimensional. A 3D primitive is any shape that has three dimensions, which are often called width, depth, and height (or X, Y, Z.) 3D shapes have a known volume if closed.

The mathematical study of 3D shapes and dimensions is called solid geometry.

Resolution of Shapes

All rounded shapes have a resolution option which controls tesselation. If resolution is set to 8, then 8 polygons are used to create 360 degrees of revolution.

This allows each design to control the amount of detail present, but beware that calculations and rendering time will also increase. For example, the number of polygons increases quadratically with each increase of the resolution for spheres.

EXAMPLE

If the resolution option is omitted, the following resolution is used.

  • CSG.defaultResolution3D = 12

OpenSCAD like functions support the fn parameter, which is the same as resolution.

Cuboid

A three dimensional shape created from six retangular faces, each at right angles to another, and opposite faces are equal. The cube is a special case of the a cuboid in which all six faces are squares.

 Cuboid

Learn about cuboids at MathIsFun.com

Cubes can be created at a requested center. The radius specifies the size of the faces. Cubes with different radius for X, Y and Z axis can be specified by supplying an array of values.

Defaults:

  • size : 1 or [1,1,1]
  • center : [0,0,0]
  • radius : 0
  • round: false
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})

Also, the CSG library functions can be used directly. NOTE Deprecated in the V2 API

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

Rounded cubes are created by specifying a rounded radius for the corners and the sides.

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

Sphere

A three dimensional shape like a ball, where every point on the surface is the same distance from the center.

Sphere

Learn about spheres at MathIsFun.com

Creates a sphere at the requested center. The radius argument determines the size of the sphere. The resolution option determines the number of segments to create in 360 degrees of rotation.

Note: See the start of 3D Primitives for information about the resolution of three dimenional shapes.

Defaults:

  • radius : 1 or [1,1,1]
  • center : [0,0,0]
  • resolution : Resolution3D (12)
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)

In case of ``type: 'geodesic'`` the fn tries to match the non-geodesic fn, yet, actually changes in steps of 6 (e.g. fn=6..11 is the same), fn = 1 reveals the base form: the icosahedron.

The CSG library functions can also be used. NOTE Deprecated in the V2 API

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

Cylinder

A three dimensional shape with two flat ends that are circular or elliptical. The cylinder has the same cross-section from one end to the other.

 Cylinder

Learn about cylinders at MathIsFun.com

The following show examples of creating cylinders. The radius specifies the size about the axis. The resolution option determines the number of segments to create in 360 degrees of rotation.

If necessary then additional options can be provide for start and end points of the axis. As well as start and end radius.

Note: See the start of 3D Primitives for information about the resolution of three dimensional shapes.

Defaults:

  • radius : 1 or
    • radiusStart : 1
    • radiusEnd : 1
  • axis :
    • start : [0,0,-1], end : [0,0,1]
  • resolution : Resolution3D (12)

Note: A start or end radius of 0 creates a cone.

cylinder({r: 1, h: 10})
cylinder({r: 1, h: 10, center: true})   // default: center:false
cylinder({r: 1, h: 10, center: [true, true, false]})
cylinder({r: 1, h: 10, round: true})
cylinder({r1: 3, r2: 0, h: 10})
cylinder({start: [0,0,0], end: [0,0,10], r1: 1, r2: 2, fn: 50})

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

CSG.cylinder({
  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
});

Torus

A three dimensional shape made by revolving a small circle (inner) along the circumference a bigger circle (outer).

 Torus

Learn about torus at MathIsFun.com

A torus is defined as such:

  • Inner Circle
    • ri = inner radius
    • fni = inner resolution
    • roti = inner rotation
  • Outer Circle
    • ro = outer radius
    • fno = outer resolution

Note: See the start of 3D Primitives for information about the resolution of three dimensional shapes.

Defaults:

  • ri : 1
  • fni : 16
  • roti : 0
  • ro : 4
  • fno : 32
torus() 
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

A three dimensional shape where connecting faces create a solid. Each face is a three dimensional polygon (a flat shape with straight sides).

Learn about polyhedrons at MathIsFun.com

Create a polyhedron with a list of points and a list of triangles or polygons. The point list is all the vertexes of the shape, the triangle list is how the points relates to the surfaces of the polyhedron

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
});

Additionally you can also define `polygons: [ [0,1,4,5], [..] ]` too, not just `triangles:`.

You can also create a polyhedron at a more low-level.

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);

2D Primitives

‘2D’ stands for two (2) dimensional. A 2D primitive is any shape that has two dimensions, which are width and length (or X and Y.) The 2D dimensional shapes have no thickness (Although, JSCAD shows a very thin shape.)

One way of thinking about 2D shapes is anything that lays flat on a piece of paper, such as drawing a circle or a square.

The mathematical study of 2D shapes and dimensions is called plane geometry.

Resolution of Shapes

All rounded shapes have a resolution option which controls tesselation. If resolution is set to 8, then 8 polygons are used to create 360 degrees of revolution.

This allows each design to control the amount of detail present, but beware that calculations and rendering time will also increase. For example, the number of polygons increases quickly with each increase of the resolution for circles.

EXAMPLE

If the resolution option is omitted, the following resolution is used.

  • CSG.defaultResolution2D = 32

OpenSCAD like functions support the fn parameter, which is the same as resolution.

Rectangle

A two dimensional shape made with four straight sides where all interior angles are right angles (90°).

Rectangle Learn about rectangles at MathIsFun.com

The following show examples of creating rectangles. The radius specifies the size. Rectangles with different radius for X and Y axis can be specified by supplying an array of values.

Defaults:

  • radius : 1 or [1,1]
  • center : [0,0]
square(5);                                  // square 5 x 5
square([2,3]);                              // rectangle 2 x 3
square({size: [2,4], center: true});        // rectangle 2 x 4, centered on both X and Y axis

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

CAG.rectangle({center: [0,0], radius: [5, 10]});
CAG.roundedRectangle({center: [0,0], radius: [10, 50], roundradius: 1, resolution: 4});

Circle

A two dimensional shape made by drawing a curve that is always the same distance from a center. All points are the same distance from the center.

Circle Learn about circles at MathIsFun.com

The following show examples of creating circles. The radius specifies the size. The resolution option determines the number of segments to create in 360 degrees of rotation.

Note: See the start of 2D Primitives for information about the resolution of two dimensional shapes.

Defaults:

  • radius : 1
  • center : [0,0]
  • resolution: defaultResolution2D (32)
let c1 = circle(1) 
let c2 = circle({r: 2, fn:5})            // fn = number of segments to approximate the circle
let c3 = circle({r: 3, center: true})

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

let c4 = CAG.circle({center: [0,0], radius: 3, resolution: 32})

Polygon

A two dimensional shape with straight sides, and the shape is “closed” (all the sides connect up).

PolygonsPolygons

Learn about polygons at MathIsFun.com

The following show examples of creating polygons from a list of points.

Defaults:

  • empty
let p1 = polygon([ [0,0],[3,0],[3,3] ])
let p2 = polygon({ points: [ [0,0],[3,0],[3,3] ] })

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

let p3 = CAG.fromPoints([ [0,0],[5,0],[3,5],[0,5] ])

Transforms

All shapes can be transformed, i.e. translated to another location, rotated by certain degrees, etc. In all cases, the transform function returns a new shape, not the original.

let circleA = circle({radius: 5})
let circleB = circleA.scale([5,10]) // a new cicle, scaled as requested

So, in order to modify the original, place that on the left-hand side of the expression.

let circleA = circle({radius: 5})
circleA = circleA.scale([5,10]) // a new circle, scaled as requested, reassigned to the original

In fact, the two lines above can be combined into a single line.

let circleA = circle({radius: 5}).scale([5,10]) // a new circle, and scaled as requested

Transforms can also be chained together.

// rotate the circle about the X axis by 45 degrees
// and translate the circle up the Z axis 10 units
// and assign the result to circleB
let circleB = circleA.rotateX(45).translate([0,0,10])

The original shape can be transformed any number of times. For example, the same cylinder can be rotated, making copies of the cylinders, and then unioned together. This is a common pattern when creating complex designs.

Orientation

The standard for all 3D systems today, including graphics cards, design tools, etc. is orientating shapes using the right-hand rule. JSCAD follows the same rules internally, and produces shapes, applies transforms, etc. using the right-hand rule of orientation.

Learn about the right-hand rule at Wikipedia.org

Rotate

Shapes can be rotated by any given degree about the X, Y, and Z axis. The degrees can be specified as either positive or negative values.

Learn about rotation at MathIsFun.com

Defaults:

  • degree : 0 or [0,0,0]
let obj = cube([5,20,5])
obj = rotate([90,15,30],obj)
obj = rotate(90,[1,0.25,0.5],obj)

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

obj.rotateX(90);
obj.rotateY(45);
obj.rotateZ(30);
 
obj.rotate(rotationCenter, rotationAxis, degrees)
obj.rotateEulerAngles(alpha, beta, gamma, position)

Scale

Shapes can be scaled by any factor. Shapes are enlarged (increases) or shrunk (diminishes) by a scale factor. The result of scaling is a similar shape (in the geometric sense) to the original.

Learn about the scaling shapes at Wikipedia.org

Defaults:

  • factor : 1.0 or [1.0,1.0,1.0]
let obj = sphere(5)
obj = scale(2,obj)
obj = scale([1,2,3],obj)

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

obj.scale([1,2,3])

Translate

Shapes can be translated (moved) to another location. In other words, every point in the shape is moved by a fixed distance in the same direction. The offset can be positive or negative.

Learn about translation at MathIsFun.com

Defaults:

  • offset : 0 or [0,0,0]
let obj = sphere(5)
obj = translate([0,0,10],obj)

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

obj.translate([0,0,10])

Center

Shapes can be centered about the X, Y or Z axis.

Note: The center of a shape is calculated as the midpoint between minimal and maximum points.

let obj = sphere(5)
obj = center(true,cube(), obj)  // center the objects across all axes
obj = center([true, true, false], obj)  // center the object across only X and Y axis

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

cube().center(true)                // center the object across all axes
cube().center([true,true,false])   // center the object across only X and Y axis

Reflect

Shapes can reflect about the X, Y, or Z axis.

Learn about reflection at MathIsFun.com

Defaults:

  • degree : 0 or [0,0,0]
let obj = cube([5, 20, 5])
obj = mirror([10, 20, 90], obj)

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

var cube = CSG.cube().translate([1,0,0])
 
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);

Matrix Transform

The previous transforms are actually simplified versions of matrix mathematics. For example, translate is just applying additition using a matrix.

Learn about matrix mathematics at MathIsFun.com

let 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:
let cube3 = cube().transform(m)

Color

Shapes can exhibit different colors. And just like the other transformations, adding color to a shape produces a new shape, one with color.

NOTE: 2D shapes cannot exhibit colors today. This is a known issue.

let a = color("Red",sphere())
let b = color([1, 0.5, 0.3],sphere())
let c = color([1, 0.5, 0.3, 0.6],sphere(10),cube(20))

See the Extended Color Keywords for all available colors. Color keywords are case-insensitive, e.g. 'RED' is the same as 'red'.

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

let a = object.setColor(css2rgb('dodgerblue'))
let b = sphere().setColor(1, 0.5, 0.3)
let c = sphere().setColor([1, 0.5, 0.3, 0.7])

Note: There are known issues with transparency, and depending on the order of colors, objects may not seem transparent. Try different 'alpha' values or colors.

Color Space Conversion

Following functions to convert between color spaces.

let rgb = css2rgb('navy')
let rgb = html2rgb('#RRGGBB')
 
let rgb = hsl2rgb(h,s,l) // or hsl2rgb([h,s,l])
let rgb = hsv2rgb(h,s,v) // or hsv2rgb([h,s,v])
 
let hsv = rgb2hsv(r,g,b) // or rgb2hsv([r,g,b])
let hsl = rgb2hsl(r,g,b) // or rgb2hsl([r,g,b])
let html = rgb2html(r,g,b)

whereas

  • r,g,b (red, green, blue)
  • h,s,l (hue, saturation, lightness)
  • h,s,v (hue, saturation, value)

Operations

All shapes (primitives or the results of operations) can be passed to special functions to perform logical operations, e.g. removing a hole from a board. In all cases, the operation returns the results, and never changes the original shapes.

Union

Several shapes can be combined (merged) into a single shape. The result is the logical union of the shapes. The combining of smaller obects together allows easier transformations, etc.

let shape = union(sphere({r: 1, center: true}), cube({size: 1.5, center: true})

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

sphere({r: 1, center: true}).union(cube({size: 1.5, center: true}))

Intersection

Several objects can be combined (overlapped) into a single shape. This result is the logical intersection of the shapes.

let shape = intersection(sphere({r: 1, center: true}), cube({size: 1.5, center: true}))

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

sphere({r: 1, center: true}). intersect(cube({size: 1.5, center: true}))

Difference

Several shapes can be removed (subtracted) from another. The result is the logical difference of shapes.

Note: The first shape given is the base shape for all subtractions.

let shape = difference(sphere({r: 1, center: true}), cube({size: 1.5, center: true}))

The CSG library functions can also be used. NOTE: Deprecated in the V2 API

sphere({r: 1, center: true}). subtract(cube({size: 1.5, center: true}))

Hull

Several shapes can be combined together to form the convex hull, i.e. sum of the outside shells. This includes irregular shapes such as combining a circle with a square.

Note: Convex hulls can be viewed as elastic wrapping around several shapes.

EXAMPLE

Learn more about convex hull at Wikipedia.org

let h = hull(square(10), translate([5, 10, 15], circle(10)))

Chain Hull

Chain Hull is a variant of Hull across multiple 2D forms, essentially sequential hulling, then creating a union of the results.

chain_hull( 
    circle(), circle().translate([2,0,0]), ... );   // list of CAG/2D forms
 
let 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]))

Extrusions

Linear Extrude

Extruding 2D shapes into 3D, given height, twist (degrees), and slices (if twist is made):

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]) );

Linear extrusion of 2D shape, with optional twist. The 2d shape is placed in in z=0 plane and extruded into direction offset (a CSG.Vector3D). The final face is rotated twistangle degrees. Rotation is done around the origin of the 2D shape (i.e. x=0, y=0) twiststeps determines the resolution of the twist (should be >= 1), returns a CSG object:

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

Rectangular Extrude

Extrude the path by following it with a rectangle (upright, perpendicular to the path direction), returns a CSG solid.

Simplified (openscad like, even though OpenSCAD doesn't provide this) via rectangular_extrude(), where as

  • w: width (default: 1),
  • h: height (default: 1),
  • fn: resolution (default: 8), and
  • closed: whether path is closed or not (default: 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});

or more low-level via rectangularExtrude(), with following unnamed variables:

  • width of the extrusion, in the z=0 plane
  • height of the extrusion in the z direction
  • resolution, number of segments per 360 degrees for the curve in a corner
  • roundEnds: if true, the ends of the polygon will be rounded, otherwise they will be flat
// 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

Additional also rotate_extrude() is available:

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] ]}) );

You can essentially extrude any 2D polygon (circle, square or polygon).

Shape Attributes

Properties

The 'property' property of a solid can be used to store metadata for the object, for example the coordinate of a specific point of interest of the solid. Whenever the object is transformed (i.e. rotated, scaled or translated), the properties are transformed with it. So the property will keep pointing to the same point of interest even after several transformations have been applied to the solid.

Properties can have any type, but only the properties of classes supporting a 'transform' method will actually be transformed. This includes CSG.Vector3D, CSG.Plane and CSG.Connector. In particular CSG.Connector properties (see below) can be very useful: these can be used to attach a solid to another solid at a predetermined location regardless of the current orientation.

It's even possible to include a CSG solid as a property of another solid. This could be used for example to define the cutout cylinders to create matching screw holes for an object. Those 'solid properties' get the same transformations as the owning solid but they will not be visible in the result of CSG operations such as union().

Other kind of properties (for example, strings) will still be included in the properties of the transformed solid, but the properties will not get any transformation when the owning solid is transformed.

All primitive solids have some predefined properties, such as the center point of a sphere (TODO: document).

The solid resulting from CSG operations (union(), subtract(), intersect()) will get the merged properties of both source solids. If identically named properties exist, only one of them will be kept.

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]);

Measurements

Bounds

The getBounds() function can be used to retrieve the bounding box of an object, returning an array with two points specifying the minimum and maximum coordinates, i.e. X, Y, Z values.

Connectors

The CSG.Connector class is intended to facilitate attaching two solids to each other at a predetermined location and orientation. For example suppose we have a CSG solid depicting a servo motor and a solid of a servo arm: by defining a Connector property for each of them, we can easily attach the servo arm to the servo motor at the correct position (i.e. the motor shaft) and orientation (i.e. arm perpendicular to the shaft) even if we don't know their current position and orientation in 3D space.

In other words Connector give us the freedom to rotate and translate objects at will without the need to keep track of their positions and boundaries. And if a third party library exposes connectors for its solids, the user of the library does not have to know the actual dimensions or shapes, only the names of the connector properties.

A CSG.Connector consist of 3 properties:

  • point: a CSG.Vector3D defining the connection point in 3D space
  • axis: a CSG.Vector3D defining the direction vector of the connection (in the case of the servo motor example it would point in the direction of the shaft)
  • normal: a CSG.Vector3D direction vector somewhat perpendicular to axis; this defines the “12 o'clock” orientation of the connection.

When connecting two connectors, the solid is transformed such that the <b>point</b> properties will be identical, the <b>axis</b> properties will have the same direction (or opposite direction if mirror == true), and the <b>normal</b>s match as much as possible.

Connectors can be connected by means of two methods: A CSG solid's connectTo() function transforms a solid such that two connectors become connected. Alternatively we can use a connector's getTransformationTo() method to obtain a transformation matrix which would connect the connectors. This can be used if we need to apply the same transform to multiple solids.

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);