0
# Boolean Operations
1
2
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.
3
4
## Capabilities
5
6
### Union
7
8
Return a new geometry representing the total space in the given geometries. Creates a single shape that encompasses all input shapes.
9
10
```javascript { .api }
11
/**
12
* Return a new geometry representing the total space in the given geometries
13
* @param {...Object} geometries - Geometries to union (supports nested arrays)
14
* @returns {Geom2|Geom3} A new geometry representing the union
15
*/
16
function union(...geometries: RecursiveArray<Geom2>): Geom2;
17
function union(...geometries: RecursiveArray<Geom3>): Geom3;
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
const { cube, sphere, union } = require('@jscad/modeling');
24
25
// Union of two overlapping cubes
26
const cube1 = cube({ size: 10, center: [0, 0, 0] });
27
const cube2 = cube({ size: 10, center: [5, 5, 5] });
28
const combined = union(cube1, cube2);
29
30
// Union of multiple shapes
31
const sphere1 = sphere({ radius: 4, center: [-3, 0, 0] });
32
const sphere2 = sphere({ radius: 4, center: [3, 0, 0] });
33
const sphere3 = sphere({ radius: 4, center: [0, 0, 6] });
34
const threeSpheres = union(sphere1, sphere2, sphere3);
35
```
36
37
### Intersection
38
39
Return a new geometry representing the intersection (overlapping space) of the given geometries.
40
41
```javascript { .api }
42
/**
43
* Return the intersection of the given geometries
44
* @param {...Object} geometries - Geometries to intersect (supports nested arrays)
45
* @returns {Geom2|Geom3} A new geometry representing the intersection
46
*/
47
function intersect(...geometries: RecursiveArray<Geom2>): Geom2;
48
function intersect(...geometries: RecursiveArray<Geom3>): Geom3;
49
```
50
51
**Usage Examples:**
52
53
```javascript
54
const { cube, sphere, intersect } = require('@jscad/modeling');
55
56
// Intersection of cube and sphere creates rounded cube corners
57
const myCube = cube({ size: 10 });
58
const mySphere = sphere({ radius: 8 });
59
const roundedCube = intersect(myCube, mySphere);
60
61
// Intersection of three cylinders for complex internal cavity
62
const { cylinder, rotateY, rotateX } = require('@jscad/modeling');
63
const cyl1 = cylinder({ height: 20, radius: 3 });
64
const cyl2 = rotateY(Math.PI/2, cylinder({ height: 20, radius: 3 }));
65
const cyl3 = rotateX(Math.PI/2, cylinder({ height: 20, radius: 3 }));
66
const tripleIntersection = intersect(cyl1, cyl2, cyl3);
67
```
68
69
### Subtraction
70
71
Return a new geometry with the first geometry minus all subsequent geometries. Removes material from the first shape.
72
73
```javascript { .api }
74
/**
75
* Return a new geometry with the first geometry minus all subsequent geometries
76
* @param {...Object} geometries - Geometries for subtraction (supports nested arrays)
77
* @returns {Geom2|Geom3} A new geometry representing the subtraction
78
*/
79
function subtract(...geometries: RecursiveArray<Geom2>): Geom2;
80
function subtract(...geometries: RecursiveArray<Geom3>): Geom3;
81
```
82
83
**Usage Examples:**
84
85
```javascript
86
const { cube, cylinder, sphere, subtract, translate } = require('@jscad/modeling');
87
88
// Create a cube with cylindrical hole
89
const baseCube = cube({ size: 20 });
90
const hole = cylinder({ height: 25, radius: 3 });
91
const cubeWithHole = subtract(baseCube, hole);
92
93
// Create complex shape by subtracting multiple objects
94
const baseShape = cube({ size: 15 });
95
const hole1 = translate([5, 5, 0], cylinder({ height: 20, radius: 2 }));
96
const hole2 = translate([-5, -5, 0], cylinder({ height: 20, radius: 2 }));
97
const sphericalCut = sphere({ radius: 8, center: [0, 0, 10] });
98
const complexShape = subtract(baseShape, hole1, hole2, sphericalCut);
99
```
100
101
### Scission
102
103
Split geometries into separate pieces along intersection boundaries. Returns an array of separate geometries.
104
105
```javascript { .api }
106
/**
107
* Split the given 3D geometries into separate pieces (3D only)
108
* @param {...Object} geometries - 3D geometries to split (supports nested arrays)
109
* @returns {Array<Geom3>} Array of separate 3D geometries
110
*/
111
function scission(...geometries: RecursiveArray<Geom3>): Array<Geom3>;
112
```
113
114
**Usage Examples:**
115
116
```javascript
117
const { cube, sphere, scission, translate } = require('@jscad/modeling');
118
119
// Split overlapping shapes into separate pieces
120
const cube1 = cube({ size: 10, center: [-3, 0, 0] });
121
const cube2 = cube({ size: 10, center: [3, 0, 0] });
122
const pieces = scission(cube1, cube2);
123
// Returns array with separate geometric pieces
124
125
// Split complex overlapping geometry
126
const sphere1 = sphere({ radius: 6, center: [0, 0, 0] });
127
const sphere2 = sphere({ radius: 6, center: [4, 4, 0] });
128
const sphere3 = sphere({ radius: 6, center: [-4, 4, 0] });
129
const splitResult = scission(sphere1, sphere2, sphere3);
130
```
131
132
## Advanced Boolean Operations
133
134
### Chained Operations
135
136
Boolean operations can be chained together to create complex shapes:
137
138
```javascript
139
const { cube, cylinder, sphere, union, subtract, intersect } = require('@jscad/modeling');
140
141
// Create a complex mechanical part
142
const base = cube({ size: [20, 15, 10] });
143
const mainHole = cylinder({ height: 12, radius: 4 });
144
const sideHole1 = translate([6, 0, 0], cylinder({ height: 8, radius: 2 }));
145
const sideHole2 = translate([-6, 0, 0], cylinder({ height: 8, radius: 2 }));
146
147
// Add rounded corners
148
const cornerRounding = sphere({ radius: 2, center: [9, 6, 4] });
149
const roundedBase = union(base, cornerRounding);
150
151
// Remove holes
152
const finalPart = subtract(roundedBase, mainHole, sideHole1, sideHole2);
153
```
154
155
### Working with 2D Shapes
156
157
Boolean operations work equally well with 2D geometries:
158
159
```javascript
160
const { circle, rectangle, polygon, union, subtract } = require('@jscad/modeling');
161
162
// Create a 2D part with holes
163
const baseRect = rectangle({ size: [20, 15] });
164
const hole1 = circle({ radius: 3, center: [5, 3] });
165
const hole2 = circle({ radius: 2, center: [-5, -3] });
166
const cutout = polygon({ points: [[8, 0], [12, 4], [8, 8], [4, 4]] });
167
168
const part2D = subtract(baseRect, hole1, hole2, cutout);
169
```
170
171
## Type Requirements and Error Handling
172
173
### Type Consistency
174
175
All geometries passed to boolean operations must be of the same type (all geom2 or all geom3):
176
177
```javascript
178
const { cube, circle, union } = require('@jscad/modeling');
179
180
const myCube = cube({ size: 5 }); // geom3
181
const myCircle = circle({ radius: 3 }); // geom2
182
183
// This will throw an error - mixed types not supported
184
// const invalid = union(myCube, myCircle); // ERROR!
185
186
// Valid - same types only
187
const cube1 = cube({ size: 5 });
188
const cube2 = cube({ size: 3 });
189
const validUnion = union(cube1, cube2); // OK
190
```
191
192
### Error Cases
193
194
Boolean functions will throw errors for:
195
- Empty geometry lists
196
- Mixed geometry types (geom2 with geom3)
197
- Invalid geometry objects
198
- Degenerate geometries that cannot be processed
199
200
## Implementation Notes
201
202
### CSG Algorithm
203
204
The boolean operations are implemented using Binary Space Partitioning (BSP) trees:
205
- Robust handling of complex intersections
206
- Maintains mesh quality through the operations
207
- Supports both 2D and 3D geometries consistently
208
209
### Performance Considerations
210
211
- Complex geometries with many faces will take longer to process
212
- Operations are CPU-intensive for high-detail meshes
213
- Consider simplifying geometry before boolean operations when possible
214
- Union operations are generally faster than subtract or intersect
215
216
### Numerical Precision
217
218
- Operations use floating-point arithmetic with inherent precision limits
219
- Very small features may be lost or cause artifacts
220
- Consider the scale of your geometry when designing boolean operations
221
222
## Type Definitions
223
224
```javascript { .api }
225
// Recursive array type for nested geometry arrays
226
type RecursiveArray<T> = Array<T | RecursiveArray<T>>;
227
228
// Core geometry types (uppercase for TypeScript definitions)
229
type Geom2 = {
230
sides: Array<Array<[number, number]>>;
231
color?: [number, number, number, number];
232
};
233
234
type Geom3 = {
235
polygons: Array<Poly3>;
236
color?: [number, number, number, number];
237
};
238
239
type Poly3 = {
240
vertices: Array<[number, number, number]>;
241
};
242
```