CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jscad--modeling

Constructive Solid Geometry (CSG) Library for 2D and 3D geometries with boolean operations, transformations, and mathematical utilities

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

booleans.mddocs/

Boolean Operations

Boolean operations allow you to perform logical operations on shapes using Constructive Solid Geometry (CSG) algorithms. All shapes (primitives or the results of operations) can be passed to boolean functions to perform logical operations like removing a hole from a board. In all cases, the functions return new results and never change the original shapes.

Capabilities

Union

Return a new geometry representing the total space in the given geometries. Creates a single shape that encompasses all input shapes.

/**
 * Return a new geometry representing the total space in the given geometries
 * @param {...Object} geometries - Geometries to union (supports nested arrays)
 * @returns {Geom2|Geom3} A new geometry representing the union
 */
function union(...geometries: RecursiveArray<Geom2>): Geom2;
function union(...geometries: RecursiveArray<Geom3>): Geom3;

Usage Examples:

const { cube, sphere, union } = require('@jscad/modeling');

// Union of two overlapping cubes
const cube1 = cube({ size: 10, center: [0, 0, 0] });
const cube2 = cube({ size: 10, center: [5, 5, 5] });
const combined = union(cube1, cube2);

// Union of multiple shapes
const sphere1 = sphere({ radius: 4, center: [-3, 0, 0] });
const sphere2 = sphere({ radius: 4, center: [3, 0, 0] });
const sphere3 = sphere({ radius: 4, center: [0, 0, 6] });
const threeSpheres = union(sphere1, sphere2, sphere3);

Intersection

Return a new geometry representing the intersection (overlapping space) of the given geometries.

/**
 * Return the intersection of the given geometries
 * @param {...Object} geometries - Geometries to intersect (supports nested arrays)
 * @returns {Geom2|Geom3} A new geometry representing the intersection
 */
function intersect(...geometries: RecursiveArray<Geom2>): Geom2;
function intersect(...geometries: RecursiveArray<Geom3>): Geom3;

Usage Examples:

const { cube, sphere, intersect } = require('@jscad/modeling');

// Intersection of cube and sphere creates rounded cube corners
const myCube = cube({ size: 10 });
const mySphere = sphere({ radius: 8 });
const roundedCube = intersect(myCube, mySphere);

// Intersection of three cylinders for complex internal cavity
const { cylinder, rotateY, rotateX } = require('@jscad/modeling');
const cyl1 = cylinder({ height: 20, radius: 3 });
const cyl2 = rotateY(Math.PI/2, cylinder({ height: 20, radius: 3 }));
const cyl3 = rotateX(Math.PI/2, cylinder({ height: 20, radius: 3 }));
const tripleIntersection = intersect(cyl1, cyl2, cyl3);

Subtraction

Return a new geometry with the first geometry minus all subsequent geometries. Removes material from the first shape.

/**
 * Return a new geometry with the first geometry minus all subsequent geometries  
 * @param {...Object} geometries - Geometries for subtraction (supports nested arrays)
 * @returns {Geom2|Geom3} A new geometry representing the subtraction
 */
function subtract(...geometries: RecursiveArray<Geom2>): Geom2;
function subtract(...geometries: RecursiveArray<Geom3>): Geom3;

Usage Examples:

const { cube, cylinder, sphere, subtract, translate } = require('@jscad/modeling');

// Create a cube with cylindrical hole
const baseCube = cube({ size: 20 });
const hole = cylinder({ height: 25, radius: 3 });
const cubeWithHole = subtract(baseCube, hole);

// Create complex shape by subtracting multiple objects
const baseShape = cube({ size: 15 });
const hole1 = translate([5, 5, 0], cylinder({ height: 20, radius: 2 }));
const hole2 = translate([-5, -5, 0], cylinder({ height: 20, radius: 2 }));
const sphericalCut = sphere({ radius: 8, center: [0, 0, 10] });
const complexShape = subtract(baseShape, hole1, hole2, sphericalCut);

Scission

Split geometries into separate pieces along intersection boundaries. Returns an array of separate geometries.

/**
 * Split the given 3D geometries into separate pieces (3D only)
 * @param {...Object} geometries - 3D geometries to split (supports nested arrays)
 * @returns {Array<Geom3>} Array of separate 3D geometries
 */
function scission(...geometries: RecursiveArray<Geom3>): Array<Geom3>;

Usage Examples:

const { cube, sphere, scission, translate } = require('@jscad/modeling');

// Split overlapping shapes into separate pieces
const cube1 = cube({ size: 10, center: [-3, 0, 0] });
const cube2 = cube({ size: 10, center: [3, 0, 0] });
const pieces = scission(cube1, cube2);
// Returns array with separate geometric pieces

// Split complex overlapping geometry
const sphere1 = sphere({ radius: 6, center: [0, 0, 0] });
const sphere2 = sphere({ radius: 6, center: [4, 4, 0] });
const sphere3 = sphere({ radius: 6, center: [-4, 4, 0] });
const splitResult = scission(sphere1, sphere2, sphere3);

Advanced Boolean Operations

Chained Operations

Boolean operations can be chained together to create complex shapes:

const { cube, cylinder, sphere, union, subtract, intersect } = require('@jscad/modeling');

// Create a complex mechanical part
const base = cube({ size: [20, 15, 10] });
const mainHole = cylinder({ height: 12, radius: 4 });
const sideHole1 = translate([6, 0, 0], cylinder({ height: 8, radius: 2 }));
const sideHole2 = translate([-6, 0, 0], cylinder({ height: 8, radius: 2 }));

// Add rounded corners
const cornerRounding = sphere({ radius: 2, center: [9, 6, 4] });
const roundedBase = union(base, cornerRounding);

// Remove holes
const finalPart = subtract(roundedBase, mainHole, sideHole1, sideHole2);

Working with 2D Shapes

Boolean operations work equally well with 2D geometries:

const { circle, rectangle, polygon, union, subtract } = require('@jscad/modeling');

// Create a 2D part with holes
const baseRect = rectangle({ size: [20, 15] });
const hole1 = circle({ radius: 3, center: [5, 3] });
const hole2 = circle({ radius: 2, center: [-5, -3] });
const cutout = polygon({ points: [[8, 0], [12, 4], [8, 8], [4, 4]] });

const part2D = subtract(baseRect, hole1, hole2, cutout);

Type Requirements and Error Handling

Type Consistency

All geometries passed to boolean operations must be of the same type (all geom2 or all geom3):

const { cube, circle, union } = require('@jscad/modeling');

const myCube = cube({ size: 5 });    // geom3
const myCircle = circle({ radius: 3 }); // geom2

// This will throw an error - mixed types not supported
// const invalid = union(myCube, myCircle); // ERROR!

// Valid - same types only
const cube1 = cube({ size: 5 });
const cube2 = cube({ size: 3 });
const validUnion = union(cube1, cube2); // OK

Error Cases

Boolean functions will throw errors for:

  • Empty geometry lists
  • Mixed geometry types (geom2 with geom3)
  • Invalid geometry objects
  • Degenerate geometries that cannot be processed

Implementation Notes

CSG Algorithm

The boolean operations are implemented using Binary Space Partitioning (BSP) trees:

  • Robust handling of complex intersections
  • Maintains mesh quality through the operations
  • Supports both 2D and 3D geometries consistently

Performance Considerations

  • Complex geometries with many faces will take longer to process
  • Operations are CPU-intensive for high-detail meshes
  • Consider simplifying geometry before boolean operations when possible
  • Union operations are generally faster than subtract or intersect

Numerical Precision

  • Operations use floating-point arithmetic with inherent precision limits
  • Very small features may be lost or cause artifacts
  • Consider the scale of your geometry when designing boolean operations

Type Definitions

// Recursive array type for nested geometry arrays
type RecursiveArray<T> = Array<T | RecursiveArray<T>>;

// Core geometry types (uppercase for TypeScript definitions)
type Geom2 = {
  sides: Array<Array<[number, number]>>;
  color?: [number, number, number, number];
};

type Geom3 = {
  polygons: Array<Poly3>;
  color?: [number, number, number, number];
};

type Poly3 = {
  vertices: Array<[number, number, number]>;
};

docs

booleans.md

colors.md

curves.md

expansions-modifiers.md

extrusions.md

geometries.md

hulls.md

index.md

maths.md

measurements.md

primitives.md

text-utils.md

transforms.md

tile.json