8.3 Boolean Operations in 2D

Aligned outcomes:

SLO 3

Describe, design, implement, and test structured programs using currently accepted methodology.

Learning Objectives

By the end of this section, you will be able to:

In this section, you will learn to:
  • combine two or more shapes with union, subtract, and intersect;
  • explain why the order of arguments matters in subtract;
  • build a washer or ring shape with a two-step subtract;
  • explain why the order of operations changes the result of nested booleans;
  • combine many shapes at once with a variadic boolean call.

All three live in JSCAD → booleans. Each takes two or more geometries of the same type (all geom2, or all geom3) and returns a new geometry — inputs are left unmodified.

Boolean means combine

In programming, a boolean operation is one that combines things with a yes/no rule. Here the "things" are shapes, and the rules are add, remove, and overlap — the same ideas as set union, subtraction, and intersection in math.

union(…geometries) → geom2|geom3

The combined space covered by every input geometry.

Editor
renders in your browser

Union works the same way on 2D shapes. Here a rectangle and a circle are joined into one outline:

Editor
renders in your browser

Union is the glue

Union joins every input into one shape. If two shapes overlap, the overlap is counted once — you get a single merged object, not two shapes sitting on top of each other.

Try It Now 8.3.1

Use union to combine two circles: one of radius 10 at the origin and one of radius 10 centered at (15, 0). Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — pick the operation. We want to join two shapes, so we use union.

Step 2 — build the two circles. The first is circle({ radius: 10 }) at the origin. The second is circle({ radius: 10, center: [15, 0] }).

Step 3 — pass both to union. union takes all the geometries as arguments.

Editor
renders in your browser

Answer: union(circle({ radius: 10 }), circle({ radius: 10, center: [15, 0] })) — one merged shape covering both circles.

subtract(…geometries) → geom2|geom3

Space in the first geometry that is not in any of the following geometries. Order matters: subtract(A, B) and subtract(B, A) are different shapes.

Editor
renders in your browser

Subtract also carves a hole that is not centered. Here a circle is bitten out of the corner of a rectangle:

Editor
renders in your browser

Order is everything

Subtract carves the first shape away using the ones that follow. Swap the arguments and you carve the other way — the result is a different shape, so always think about which shape you are keeping.

Example 8.3.1: Which shape do you keep?

subtract keeps the first shape and carves the rest out of it — so the argument you put first is the one that survives. Build a rectangle and cut a hole out of its middle; each comment below is one line for you to write. Press Run when you are done.

Editor
renders in your browser

Solution
Editor
renders in your browser

You should see a 20-by-10 rectangle with a radius-4 hole in its middle. The rectangle went first, so it is the shape kept. Now swap the arguments — subtract(hole, base) — and run it again: you get the circle with a rectangle bitten out of it instead. Same two shapes, different result, because the first argument is the survivor.

Try It Now 8.3.2

Use subtract to remove a radius-4 circle from a radius-10 circle, both centered at the origin. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — pick the operation. We want to remove one shape from another, so we use subtract.

Step 2 — decide which shape to keep. We keep the radius-10 circle, so it goes first.

Step 3 — build the two circles and subtract. The first argument is circle({ radius: 10 }); the second is circle({ radius: 4 }).

Editor
renders in your browser

Answer: subtract(circle({ radius: 10 }), circle({ radius: 4 })) — a ring with a radius-4 hole in the middle.

intersect(…geometries) → geom2|geom3

Only the space present in all input geometries — the overlap.

Editor
renders in your browser

Intersect works the same way on 2D shapes. Here a rectangle and a circle overlap, and only the shared space survives:

Editor
renders in your browser

Intersect keeps only the overlap

Where union keeps everything and subtract keeps one minus the other, intersect keeps only the part that is in every input at once. If two shapes barely touch, intersect returns a sliver.

Try It Now 8.3.3

Use intersect to find the overlap of two circles: one of radius 10 at the origin and one of radius 10 centered at (15, 0). Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — pick the operation. We want only the shared space, so we use intersect.

Step 2 — build the two circles. The first is circle({ radius: 10 }) at the origin. The second is circle({ radius: 10, center: [15, 0] }).

Step 3 — pass both to intersect.

Editor
renders in your browser

Answer: intersect(circle({ radius: 10 }), circle({ radius: 10, center: [15, 0] })) — the lens-shaped overlap where the two circles meet.

Combining booleans

A washer/ring is a canonical two-step subtract:

Editor
renders in your browser

The washer is the classic first part

A washer is just a big circle with a smaller circle cut out of its middle. It is the simplest real part you can make with booleans, and it shows how subtract turns two shapes into one useful object.

Booleans chain

You are not limited to one operation. Build a washer with subtract, then union it with other shapes, or subtract again to add more holes — the operations combine to make complex parts.

Example 8.3.2: A complete washer script

The washer is the classic first boolean part: a big circle with a smaller one cut out of its middle. This version is a full script — imports, a main, and an export — not just one line. Each comment below is one line for you to write. Press Run when you are done.

Editor
renders in your browser

Solution
Editor
renders in your browser

You should see a washer — a radius-20 circle with a radius-12 hole cut from its center. The outer circle is the first argument, so it is the shape that survives. Change the inner radius to 8 and run it again: the hole grows and the ring of material gets thinner.

Try It Now 8.3.4

Write a complete JSCAD script that builds a washer with an outer radius of 30 and an inner radius of 18.

Editor
renders in your browser

Solution

Step 1 — import the functions. We need circle from primitives and subtract from booleans.

Step 2 — set the radii. The outer radius is 30 and the inner radius is 18.

Step 3 — subtract the inner circle from the outer circle. The outer circle goes first so it is the shape we keep.

Editor
renders in your browser

Answer: The script above returns a washer — a radius-30 circle with a radius-18 hole cut from its center.

Order of operations

Booleans nest, and the order you nest them changes the result. subtract(union(a, b), c) first joins a and b, then carves c out of the whole. union(subtract(a, c), b) first carves c out of a alone, then joins the result with b. When c overlaps the join between a and b, the two orders carve different shapes.

Editor
renders in your browser

Editor
renders in your browser

The order of operations is the most common student error

In the first fence, c sits right on the seam where a and b meet, so carving it out of the union leaves a clean hole through the middle. In the second, c is carved out of a before b is added, so the hole is only in a — the seam stays solid. Same three shapes, different result, because the parentheses decide what happens first.

Try It Now 8.3.5

Using the shapes a = circle({ radius: 10 }), b = circle({ radius: 10, center: [15, 0] }), and c = circle({ radius: 4, center: [7.5, 0] }), write the JSCAD call that carves c out of a first, then joins the result with b.

Editor
renders in your browser

Solution

Step 1 — decide the order. We carve c out of a first, so subtract(a, c) comes first.

Step 2 — join the result with b. The carved a is the first argument to union, and b is the second.

Editor
renders in your browser

Answer: union(subtract(a, c), b) — the hole is carved into a alone, then b is joined on, so the seam stays solid.

Booleans on many shapes at once

All three operations take a variadic list — you can pass as many geometries as you like, and they are combined in one call. union(a, b, c, d) joins all four. You can also spread an array of shapes into the call with the ... operator.

Editor
renders in your browser

Variadic means "any number of arguments."

A variadic function accepts a list of arguments of any length, so union can take two shapes or twenty. When your shapes already live in an array, spread them in: union(...shapes) is the same as listing them out by hand.

Try It Now 8.3.6

Write a JSCAD call that joins four circles of radius 8 centered at (0, 0), (12, 0), (0, 12), and (12, 12) using a single union call.

Editor
renders in your browser

Solution

Step 1 — build the four circles. Each is circle({ radius: 8 }) with a different center.

Step 2 — pass all four to one union call. union is variadic, so it takes all four geometries as arguments.

Editor
renders in your browser

Answer: union(circle({ radius: 8 }), circle({ radius: 8, center: [12, 0] }), circle({ radius: 8, center: [0, 12] }), circle({ radius: 8, center: [12, 12] })) — one merged shape covering all four circles.

Problem Set

Problem 1. In your own words, describe what each of union, subtract, and intersect does to a set of input shapes.

Problem 2. Explain why subtract(A, B) and subtract(B, A) produce different shapes. Give a concrete example.

Problem 3. Write a JSCAD call that uses union to join a rectangle of size [10, 20] and a circle of radius 5 centered at (10, 0).

Problem 4. Write a JSCAD call that uses subtract to remove a radius-3 circle from a radius-8 circle, both centered at the origin.

Problem 5. Write a JSCAD call that uses intersect to find the overlap of a rectangle of size [10, 10] and a circle of radius 8 centered at (5, 5).

Problem 6. Write a complete JSCAD script that builds a washer with an outer radius of 25 and an inner radius of 10.

Problem 7. Using the shapes a = circle({ radius: 10 }), b = circle({ radius: 10, center: [15, 0] }), and c = circle({ radius: 4, center: [7.5, 0] }), write the JSCAD call that joins a and b first, then carves c out of the result.

Problem 8. Write a JSCAD call that joins four circles of radius 8 centered at (0, 0), (12, 0), (0, 12), and (12, 12) using a single union call.

Key Terms

boolean operation — a way of combining shapes with a yes/no rule: union, subtract, or intersect.

union — the combined space covered by every input geometry.

subtract — the space in the first geometry that is not in any of the following geometries.

intersect — only the space present in all input geometries, the overlap.

geom2 / geom3 — the object types JSCAD uses for 2D and 3D geometry; boolean operations require inputs of the same type.

variadic — a function that accepts any number of arguments, so union(a, b, c, d) can take two shapes or twenty.

order of operations — the sequence in which nested boolean operations are evaluated, decided by the parentheses; changing it changes the result.