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 design (script) must have at least one function defined, the main() function, which must to return a shape.

const { sphere } = require('@jscad/modeling').primitives
 
const main = () => {
  return sphere() // a single shape
}
 
module.exports = { main }

Or an array of shapes.

const { cube, cylinder, sphere } = require('@jscad/modeling').primitives
 
const main () => {
  const a = cube()
  const b = sphere()
  const c = cylinder()
  return [a,b,c] // an array of shapes
}
 
module.exports = { main }

In addition, functions can be created to split the design into managable pieces, i.e. parts, etc.

const { cube, sphere } = require('@jscad/modeling').primitives
 
const partA = (options) => { // called from main() below
  var shapes = []
  shapes.push( sphere() )
  shapes.push( cube(options) )
  return shapes
}
 
const main = () => {
  let list = partA({radius: 10})
  return list
}
 
module.exports = { main }

Projects

As designs grow in complexity, the need for smaller, reusable parts becomes apparent. This is the time to consider using a “project”.

Projects are simple directories, containing several files (parts) of the design. For example, a project for a RC car design would have various parts. And the reusable parts can be separated out.

  • …/rc-car
    • chassis.js
    • body.js
    • tire.js
    • index.js

The 'index' within the project is the entry point of the project. The main function of the 'index' creates each of the pieces, move the pieces into position, and returns the complete design. And by convention, exports the main function.

const chassis = require('./chassis')
const body = require('./body')
const tire = require('./tire')
 
const main = (params) => {
  const partA = chassis(params)
  const partB = body(params)
  const tires = [
    ...
  ]
  return [partA, partB, tires]
}
 
module.exports = { main }

Projects can also be used when working with external formats, such as STL files. This allows designs to include STL meshes just like any other part. The STL file is placed within the project directory just like any other part.

  • …/rc-car
    • chassis.js
    • body.js
    • tire.js
    • index.js
    • rc_receiver.stl

And the design is adjusted to include the new part from the STL file.

const chassis = require('./chassis')
const body = require('./body')
const tire = require('./tire')
const receiver = require('./rc_receiver.stl')
 
const main = (params) => {
  const partA = chassis(params)
  const partB = body(params)
  const tires = [
    ...
  ]
  return [partA, partB, tires, receiver]
}
 
module.exports = { main }

Design Parameters

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

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

Usage

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

const 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.

const 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

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

There is one more special parameter type called 'choice', which defines a list of choices for selection.

const getParameterDefinitions = () => {
  return [
    { name: 'rounded', type: 'choice', caption: 'Rounded edges', values: [0, 1], captions: ['No', 'Yes (slow!)'], initial: 0 }
  ]
}

The list of captions are those shown as a pull down list. The list of values define a value for each caption. And, the chosen value is passed into the main function.

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 segments option which controls tesselation. If segments is set to 8, then 8 polygons are used to create a full revolution. If the segments option is omitted, the default value is used.

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 segments for spheres.

Sometimes, a design requires a certain degree of resolution which is expressed in the length between points, or the angle between points. If this is the case, then use the conversion function to calculate the required segments. See Conversions

Cuboid

A three dimensional shape created from six retangular faces, each at right angles to another, and opposite faces are equal.


Learn about cuboids at MathIsFun.com

The size specifies the size of each face spanning X, Y and Z axis. Cuboids can be created at a requested center.

Defaults:

  • size : [2, 2, 2]
  • center : [0, 0, 0]
const { cuboid } = require('@jscad/modeling').primitives
 
const myshape = cuboid({size: [1, 2, 3]})
const myshape = cuboid({size: [1, 2, 3], center: [4, 5, 6]})

Cube

 Cube

The cube is a special case of the cuboid in which all six faces are squares.

Defaults:

  • size : 2
  • center : [0, 0, 0]
const { cube } = require('@jscad/modeling').primitives
 
const myshape = cube({size: 3})
const myshape = cube({size: 3, center: [4, 5, 6]})

Rounded Cuboid

 Rounded Cuboid

Rounded cuboids can be created by specifying a roundRadius for the corners.

Defaults:

  • size : [2, 2, 2]
  • center : [0, 0, 0]
  • roundRadius : 0.2
  • segments : 32
const { roundedCuboid } = require('@jscad/modeling').primitives
 
const myshape = roundedCuboid({size: [1, 2, 3], roundRadius: 0.25})
const myshape = roundedCuboid({size: [1, 2, 3], roundRadius: 0.25, center: [4, 5, 6], segments: 32})

Ellipsoid

A three dimensional surface that has three pairwise perpendicular axes of symmetry which intersect at a center.

 Sphere

The radius determines the size of the ellipsoid about the X, Y, and Z axis. Ellipsoids can be created at a requested center. The segments specify the number of segments to create per full rotation.

Defaults:

  • radius : [1, 1, 1]
  • center : [0, 0, 0]
  • segments : 32
const { ellipsoid } = require('@jscad/modeling').primitives
 
const myshape = ellipsoid({radius: [5, 10, 20]})
const myshape = ellipsoid({radius: [5, 10, 20], center: [5, 5, 5], segments: 64})

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

The radius determines the size of the sphere. Spheres can be created at a requested center. The segments specify the number of segments to create per full rotation.

Defaults:

  • radius : 1
  • center : [0, 0, 0]
  • segments : 32
const { sphere } = require('@jscad/modeling').primitives
 
const myshape = sphere({radius: 3.5})
const myshape = sphere({radius: 3.5, center: [5, 5, 5], segments: 64})

Geodesic Sphere

 Geodesic Sphere

A three dimensional shape formed by a convex polyhedron consisting of triangles. The base form is the icosahedron polyhedron with 20 faces.

The radius determines the size of the sphere. The frequency specifies the division of each face. A frequency of one (1) reveals the base form, icosahedron.

Defaults:

  • radius : 1
  • frequency : 6
const { geodesicSphere } = require('@jscad/modeling').primitives
 
const myshape = geodesicSphere({radius: 15, frequency: 18}) // frequency should be a multiple of 6

Cylinder

A three dimensional shape with two flat ends that are circular. The cylinder has the same cross-section from one end to the other, extending about the Z axis.


Learn about cylinders at MathIsFun.com

The radius specifies the circular size about the Z axis, while the height specifies the size. Cylinders can be created at a requested center. The segments specify the number of segments to create per full rotation.

Defaults:

  • radius : 1
  • height : 2
  • center : [0, 0, 0]
  • segments : 32
const { cylinder } = require('@jscad/modeling').primitives
 
const myshape = cylinder({radius: 5, height: 10})
const myshape = cylinder({radius: 5, height: 10, center: [5, 5, 5], segments: 64})

Elliptical Cylinder

 Cylinder Elliptic

Various cylindrical shapes can be created using the elliptical cylinder, including cylinders with changing radius (cones).

Defaults:

  • height : 2
  • startRadius : [1, 1]
  • endRadius : [1, 1]
  • center : [0, 0, 0]
  • segments : 32
  • startAngle : 0
  • endAngle : PI * 2
const { cylinderElliptic } = require('@jscad/modeling').primitives
 
const myshape = cylinderElliptic({height: 2, startRadius: [10, 5], endRadius: [8, 3]})

Rounded Cylinder

 Rounded Cylinder

Cylinders can be created with rounded ends by specifying roundRadius.

Defaults:

  • radius : 1
  • height : 2
  • roundRadius: 0.5
  • center : [0, 0, 0]
  • segments : 32
const { roundedCylinder } = require('@jscad/modeling').primitives
 
const myshape = roundedCylinder({radius: 5, height: 10, roundRadius: 0.5})
const myshape = roundedCylinder({radius: 5, height: 10, roundRadius: 0.5, center: [5, 5, 5], segments: 64})

Torus

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


Learn about torus at MathIsFun.com

A torus is defined as such:

  • Inner Circle
    • inner radius
    • inner rotation before rotating about the outer circle
    • inner segments
  • Outer Circle
    • outer radius
    • outer segments
  • Rotation
    • start angle of rotation
    • outer rotation

Defaults:

  • innerRadius : 1
  • innerRotation : 0
  • innerSegments : 32
  • outerRadius : 4
  • outerSegments : 32
  • startAngle : 0
  • outerRotation : PI * 2
const { torus } = require('@jscad/modeling').primitives
 
const myshape = torus({innerRadius: 10, outerRadius: 100})

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 from a list of points and a list of faces. The points list all the vertexes of the shape, while the faces define the points used within each face.

Note: The order of the points must be consistent, defining 'inward' or 'outward' facing polygons.

const { polyhedron } = require('@jscad/modeling').primitives
 
const points = [ [10, 10, 0], [10, -10, 0], [-10, -10, 0], [-10, 10, 0], [0, 0, 10] ]
const faces = [ [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4], [1, 0, 3], [2, 1, 3] ]
const myshape = polyhedron({points, faces, orientation: 'inward'})

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 segments option which controls tessellation. If segments is set to 8, then 8 segments are used to create PI * 2 radians of revolution. If the segments option is omitted, the default value is used.

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 segments for spheres.

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 size specifies the size across X and Y axis. Rectangles can be created at a requested center.

Defaults:

  • size : [2, 2]
  • center : [0, 0]
const { rectangle } = require('@jscad/modeling').primitives
 
const myshape = rectangle({size: [3, 4]})
const myshape = rectangle({size: [3, 4], center: [5, 5]})

Square

 Square

The specialized square primitive also exists, but requires only one number value for all sides.

Defaults:

  • size : 2
  • center : [0, 0]
const { square } = require('@jscad/modeling').primitives
 
const myshape = square({size: 3})
const myshape = square({size: 3, center: [5, 5]})

Rounded Rectangle


Rounded rectangles can be created by specifying a roundRadius for the corners.

Defaults:

  • size : [2, 2]
  • center : [0, 0]
  • roundedRadius: 0.2
  • segments: 32
const { roundedRectangle } = require('@jscad/modeling').primitives
 
const myshape = roundedRectangle({size: [10, 20], roundRadius: 2})
const myshape = roundedRectangle({size: [10, 20], roundRadius: 2, center: [5, 5], segments: 64})

Ellipse


A two dimensional shape that surrounds two focal points, such that for all points on the curve, the sum of the two distances to the focal points is a constant.

The radius determines the size of the ellipsoid about X and Y axis. Ellipsoids can be created at a requested center. The segments specify the number of segments to create per full rotation.

Defaults:

  • radius : [1, 1]
  • center : [0, 0]
  • startAngle : 0
  • endAngle : PI * 2
  • segments: 32
const { ellipse } = require('@jscad/modeling').primitives
 
const myshape = ellipse({radius: [5, 10]})
const myshape = ellipse({radius: [5, 10], center: [5, 5], startAngle: Math.PI / 2, endAngle: Math.PI, segments: 64})

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.


Learn about circles at MathIsFun.com

The radius specifies the size across both X and Y axis. Circles can be created at a requested center. The segments specify the number of segments to create per full rotation.

Defaults:

  • radius : 1
  • center : [0, 0]
  • segments: 32
const { circle } = require('@jscad/modeling').primitives
 
const myshape = circle({radius: 10})
const myshape = circle({radius: 10, center: [5, 5], startAngle: Math.PI / 2, endAngle: Math.PI, segments: 64})

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

NOTE: The ordering of points is VERY IMPORTANT. If the polygon is going to be extruded then the points must be in counter-clockwise order, otherwise the faces of the object will be facing inwards. See Orientation.

HINT: Polygons should have a positive area.

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

Defaults:

  • empty
const { polygon } = require('@jscad/modeling').primitives
 
const myshape = polygon({ points: [ [0,0],[3,0],[3,3] ] })

Star


A two dimensional shape made from straight rays extending from a center. All vertices are the same distance from the center.

Note: See the paper on The Inner Radius of n/m Stars by Julian D. A. Wiseman for more details.

Defaults:

  • vertices : 5
  • density : 2
  • outerRadius : 1
  • innerRadius : 0
  • startAngle : 0
  • center : [0, 0, 0]
const { star } = require('@jscad/modeling').primitives
 
let star1 = star({vertices: 8, outerRadius: 10}) // star with 8/2 density
let star2 = star({vertices: 12, outerRadius: 40, innerRadius: 20}) // star with given radius

Transforms

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

const myshape = circle({radius: 5})
const newshape = scale([5, 10], circleA) // a new cicle, scaled as requested

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

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

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

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

Transforms can also be chained together, but keep in mind that the order of transforms is important.

let myshape = scale([5, 10]). circle({radius: 5}))
myshape = translate([0, 0, 10]), rotateX(45, myshape))

The original shape can be transformed any number of times. For example, the a single cylinder can be rotated and translated to make multiple copies of the original. And then, the set of cylinders can be combined together using union. This is a common pattern when creating complex designs.

The transforms return a single shape or an array of shapes depending on the given shapes.

const newshape = align({modes: ['none', 'center', 'none']}, oldshape)  /* Returns a single shape */
const newshapes = align({modes: ['min', 'center', 'none'], alignTo: [10, null, 10], grouped: true }, oldshape, [oldshape0, oldshape1])  /* Returns an array of new shapes*/

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. See Orientation for more information.

Rotate

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

Learn about rotation at MathIsFun.com

Defaults:

  • angles : [0, 0, 0]
const { cuboid } = require('@jscad/modeling').primitives
const { rotate } = require('@jscad/modeling').transforms
 
const myshape = cuboid({size: [5, 20, 5]})
const newshape = rotate([(Math.PI * 2 / 4), (Math.PI * 2 / 24), (Math.PI * 2 / 12)], myshape)

In addition, there are simple versions of the same function for rotating about a single axis.

const { cuboid } = require('@jscad/modeling').primitives
const { rotateX,rotateY,rotateZ } = require('@jscad/modeling').transforms
 
const myshape = cuboid({size: [5, 20, 5]})
let newshape = rotateX((Math.PI * 2 / 4), myshape)
newshape = rotateY((Math.PI * 2 / 24), newshape)
newshape = rotateZ((Math.PI * 2 / 12), newshape)

There is a utility function to convert DEGREE to RADIAN values.

const { cuboid } = require('@jscad/modeling').primitives
const { rotateX,rotate } = require('@jscad/modeling').transforms
const { degToRad } = require('@jscad/modeling').utils
 
const myshape = cuboid({size: [5, 20, 5]})
const newshape = rotate([degToRad(90), degToRad(15), degToRad(30)], myshape)
const newshape = rotateX(degToRad(90), myshape)

Scale

Shapes can be scaled by any factor, enlarging (increasing) or shrinking (diminishing) shapes by the factors about X, Y, and Z axis. The result of scaling is a similar shape (in the geometric sense) to the original.

Learn about the scaling shapes at Wikipedia.org

Defaults:

  • factors : [1.0, 1.0, 1.0]
const myshape = sphere({radius: 5})
const newshape = scale([2, 4, 6], myshape)

In addition, there are simple versions of the same function for scaling about a single axis.

const myshape = sphere({radius: 5})
let newshape = scaleX(2, myshape)
newshape = scaleY(4, newshape)
newshape = scaleZ(6, newshape)

Translate

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

Learn about translation at MathIsFun.com

Defaults:

  • offset : [0, 0, 0]
const myshape = sphere([radius: 5})
const newshape = translate([3, 7, -10], myshape)

In addition, there are simple versions of the same function for translating about a single axis.

const myshape = sphere([radius: 5})
let newshape = translateX(3, myshape)
newshape = translateY(7, newshape)
newshape = translateZ(-10, newshape)

Align

Shapes can be aligned across X, Y, and Z axis. In other words, each shape is translated to the requested position, aligning the boundaries of the shapes. The modes of alignment control which position to use, with values 'center', 'min', 'max', or 'none'. The alignment can also be positioned to a specific point, relativeTo.

Defaults:

  • modes : ['center', 'center', 'min']
  • group : false (do not align all shapes as a group)
  • relativeTo : [0, 0, 0]
const newshapes = align({modes: ['min', 'none', 'none'], myshape1, myshape2, myshape3) // align shapes at the minimum X
const newshapes = align({modes: ['min', 'center', 'none'], relativeTo: [10, null, 10], grouped: true}, myshape1, myshape2, myshape3)

Center

Shapes can be centered about the X, Y or Z axis, or centered relative to a given point.

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

Defaults:

  • axes : [true, true, true]
  • relativeTo : [0, 0, 0]
const myshape = sphere({radius: 5})
let newshape = center({}, myshape)  // center the shape across all axes
newshape = center({axes: [true, true, false]}, myshape)  // center the object across only X and Y axis
newshape = center({relativeTo: [5, 6, 7]}, myshape)  // center the shape relative to the given point

There are also simple versions of this function to center the shape about the origin.

const myshape = sphere({radius: 5})
let newshape = centerX(myshape)
newshape = centerY(newshape)
newshape = centerZ(newshape)

Mirror

Shapes can mirror (reflect) about the X, Y, or Z axis, and more specifically about any origin.

Learn about reflection at MathIsFun.com

Defaults:

  • origin : [0, 0, 0]
  • normal : [0, 0, 1] (mirror about the Z axis)
const myshape = cube({size: [5, 20, 5]})
const newshape = mirror({origin: 3, 3, 3], normal: [1, 0, 1]}, myshape)

There are simple versions of this function to mirror a single axis about the origin.

const myshape = cube({size: [5, 20, 5]})
let newshape = mirrorX(myshape)
newshape = mirrorY(newshape)
newshape = mirrorZ(newshape)

Matrix Transform

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

Learn about matrix mathematics at MathIsFun.com

let matrix = mat4.create()
matrix = mat4.multiply(mat4.rotationX(40))
matrix = mat4.multiply(mat4.rotationZ(40))
matrix = mat4.multiply(mat4.translation([-.5, 0, 0]))
matrix = mat4.multiply(mat4.scaling([1.1, 1.2, 1.3]))
 
// and apply the transform
const myshape = transform(matrix, cube())

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

 Union

Several shapes can be combined (merged) into a single shape, creating complex 'parts'. The combining of smaller obects together allows the 'part' to be used in other operations, transformations, etc.

const newshape = union(cube({size: 10}), cylinder({radius: 4, heigth: 14})

Intersect

 Intersect

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

const newshape = intersect(cube({size: 10}), cylinder({radius: 4, heigth: 14})

Subtract

 Subtract

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.

const newshape = subtract(cube({size: 10}), cylinder({radius: 4, heigth: 14})

Hull

 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.

Learn more about convex hull at Wikipedia.org

const newshape = hull(shape1, shape2, shape3)

Hull Chain

 Hull Chain

Hull chain is a variant of 'hull' essentially sequential hulling each pair of shapes, then creating a union of the results.

const newshape = hullChain(shape1, shape2, shape3)

Scission

'Scission' meaning “The act of cutting or dividing, as with an edged instrument”

 Union

Sometimes complex shapes need to be divided into the smaller pieces. A good example is when creating 'molds' from the pieces of a boolean operation. Or splitting a complex shape into the component pieces from an imported design, i.e. splitting STL models.

const newshapes = scission(bigshape) // expect an array containing the pieces

Extrusions

Extruding a two dimensional shape into a three dimensional shape can be performed in various ways. In each extrusion process, a continuous three dimensional shape is formed with a constant cross section similar to that of the two dimensional shape.

NOTE: In order for extrusions to produce correct shapes, the initial two dimensional shape must have the proper orientation. See Orientation below.

Linear Extrude

 Extrude Linear

Extrude a two dimensional shape in an upward linear direction.

The two dimensional shape is extruded to the height, upwards along the Z axis. The two dimensional shape is be rotated twistAngle about the Z axis during the extrusion, creating twistSteps during the extrusion.

Note: The two dimensional shape can be placed anywhere to create various twisted shapes.

Defaults:

  • height : 1
  • twist : 0
  • twistSteps : 1 (Note: Increasing the value of twistSteps improves the overall shape.)
const { extrudeLinear } = require('@jscad/modeling').extrusions
 
const myshape = extrudeLinear({height: radiusZ * 2}, shape1)
const myshape = extrudeLinear({height: radiusZ * 2, twistAngle: Math.PI / 2, twistSteps: 10}, shape2)

Rectangular Extrude

 Extrude Rectangular

Extrude a rectangle (upright, perpendicular) along the outlines of the two dimensional shape.

The two dimensional shape is extruded to the height, upwards along the Z axis.

Note: The extrusion process uses Linear Extrude underneath, so the extrusion can be rotated twistAngle about the Z axis during the extrusion, creating twistSteps during the extrusion.

Defaults:

  • size: 1 (width of rectangle during extrusion)
  • height : 1
const myshape = extrudeRectangular({height: radiusZ * 2, size: 0.25}, shape1)
const myshape = extrudeRectangular({height: radiusZ * 2, size: 3, twistAngle: Math.PI / 2, twistSteps: 10}, shape2)

Rotate Extrude

 Extrude Rotate

Extrude a two dimensional shape in a rotation about the Z axis. The two dimensional shape can be placed anywhere to create various three dimensional shapes. The segments specify the number of segments to create per full rotation.

Defaults:

  • startAngle : 0
  • angle: PI * 2
  • overflow: 'cap' (cap the ends in order to create a solid)
  • segments: 12 (Note: Increasing the value of segments improves the overall shape.)
const myshape = extrudeRotate({segments: 64}, shape1)
const myshape = extrudeRotate({segments: 8, angle: Math.PI startAngle: 0}, shape3)

Projections

The projection of a shape is a two dimensional representation of a three dimensional object. In this case, the projection is a parallel projection where the lines of projection are parallel, i.e. the projection is the same whether the shape is far away or near to the projection plane.

Project

add diagram

The outlines of three dimension shapes can be projected to two dimensional space. The 'axis' and 'origin' define the plane of which to project, which can be positioned anywhere about the shape.

Defaults: (Z Axis)

  • axis : [0, 0, 1]
  • origin: [0, 0, 0]
const myshape = project({}, sphere({radius: 20, segments: 5}))

Expansions / Offsets

All shapes (primitives or the results of operations) can be passed to special functions to expand (enlarge) or contract (lessen) a shape. In all cases, the operation returns the results, and never changes the original shapes.

Expand

 Expand

Note: The original shape is black.

Expanding two or three dimensional shapes can be performed, which maintains a specific delta distance from the shape. The corners can be filled with 'edge', 'round“, or 'chamfer' edges.

The opposite is also possible by specifying a negative (-) delta, a shape can be contracted.

Defaults:

  • delta : 1
  • corners : 'edge'
  • segments : 16
const myshape = expand({corners: 'round'}, shape1)
const myshape = expand({delta: -2}, shape2)
const myshape = expand({delta: 2}, shape3)

Note: Expanding three dimensional shapes is very CPU intensive. This is a known issue.

Offset

 Offset

Note: The original shape is black.

Offsetting two or three dimensional shapes can be performed, which maintains a specific delta distance from the shape. The corners can be filled with 'edge', 'round“, or 'chamfer' edges.

The opposite is also possible by specifying a negative (-) delta.

Defaults:

  • delta : 1
  • corners : 'edge'
  • segments : 16
const myshape = offset({corners: 'round'}, shape1)
const myshape = offset({delta: -2}, shape2)
const myshape = offset({delta: 2}, shape3)

Note: Offsetting three dimensional shapes NOT possible today. This is a known issue.

Shape Attributes

at

Color

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

Colors are not only important for visual rendering but also controlling the selection of filaments during 3D printing. Therefore, colors should be applied as the last step in designs to insure proper printing.

const myshape = colorize([1, 0, 0], sphere()) // RGB red
const myshape = colorize([1, 0.5, 0.3], sphere()) // color
const myshape = colorize([1, 0.5, 0.3, 0.6], sphere()) // color plus alpha transparency

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

There are several functions to convert between color spaces, including color names.

const wildcylinder = colorize(colorNameToRgb('fuchsia'), cylinder())
 
const bluesphere = colorize(hexToRgb('#000080'), sphere()) // navy blue
 
const mysphere = colorize(hslToRgb([0.9166666666666666, 1, 0.5]), sphere())
 
const mysphere = colorize(hsvToRgb([0.9166666666666666, 1, 1]), sphere())

whereas

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

Measurements

Sometimes the measurements of a shape can assist when creating a design. This is especially true for shapes imported from external formats.

const { measureArea, measureBoundingBox, measureVolume } = require('@jscad/modeling').measurements

Area

Measuring the area of a shape is possible, for both 2D and 3D shapes.

let area = measureArea(sphere())

Note: The area for a path is always zero(0) as paths are infinitely thin.

In addition, the total (aggregate) area for the given geometries can be measured.

let totalArea = measureAggregateArea(sphere(),cube())

Note: This measurement will not account for overlapping geometry.

Bounding Box

Measuring the bounding box (min and max bounds) of a shape is possible.

The measureBoundingBox 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.

let bounds = measureBoundingBox(sphere())

In addition, the total (aggregate) bounding box for the given geometries can be measured.

let totalBounds = measureAggregateBoundingBox(sphere(),cube())

Bounding Sphere

Measuring the (approximate) bounding sphere of a shape is possible.

let bounds = measureBoundingSphere(cube())

Center

Measuring the center of a shape is possible.

let center = measureCenter(sphere())

Note: This is equivalent to the center of the bounding box.

Center of Mass

Measuring the center of mass of a shape is possible.

let center = measureCenterOfMass(sphere())

Note: The center of mass for a path is always zero(0) as paths are infinitely thin.

Dimensions

Measuring the dimensions of a shape is possible, i.e. width, depth, and height of a shape.

let dimensions = measureDimensions(sphere())

Note: This is the equivalent width, depth, height of the bounding box.

Epsilon

Measuring the epsilon of shapes is possible. Epsilon values are used in various functions to determine minimum distances between points, planes, etc.

let epsilon = measureEpsilon(sphere())

In addition, the combined epsilon for a group geometries can be measured.

let groupEpsilon = measureAggregateEpsilon(sphere(),cube())

Volume

Measuring the volume of a shape is possible.

let volume = measureVolume(sphere())

Note: The volume of 2D shapes is always zero(0).

In addition, the total (aggregate) volume for the given geometries can be measured.

let totalVolume = measureAggregateVolume(sphere(),cube())

Note: This measurement will not account for overlapping geometry.