Cutting Shapes

Why Cut Shapes

Last lesson was about combining shapes into one. Sometimes you want the opposite: cut a shape out of another one. difference(base, *subtract) starts with base and removes every shape listed after it.

That’s a block with a cylindrical hole drilled straight through it.

Drilling a Hole, the Short Way

Drilling a hole is such a common thing to want that there’s a shortcut: hole=True.

Same result as the difference() example above, without writing difference() yourself. hole=True marks a shape as “not really there” – at the very end, every hole-marked shape gets subtracted from everything else in the scene.

Box(3, 3, 2) and Cylinder(0.6, 3, z=-0.5, hole=True) on two separate lines, not wrapped in difference(). What do you see?

Cutting in Place

a.subtract(b) cuts b out of a, in place – the same idea as a.add(b) from the last lesson, just removing instead of adding. a -= b means the same thing.

Notice this one doesn’t need hole=True at all – you already have both shapes in hand, so you can cut directly.

a = Box(3, 3, 2), then a -= Cylinder(0.6, 3, z=-0.5). What best describes what just happened?

A Hole Stays a Hole, However You Combine It

hole=True means the same thing everywhere, not just for a shape left completely on its own. If you +/union() a hole-marked shape together with a regular one, the hole still gets cut out of the regular one, right away – +/union()/add() check whether an ingredient is a hole before deciding what to do with it, instead of just gluing everything together no matter what.

block = Box(4, 4, 2), peg = Cylinder(0.5, 3, z=-0.5, hole=True), then combo = block + peg. What does combo actually look like?

This works no matter which side does the combining – block + peg, peg + block, union(block, peg), and block.add(peg) (or block += peg) all cut the same hole, because each of those checks its ingredients for hole=True first. The one operation that always cuts, whether or not anything involved is marked hole=True, is the explicit difference(block, peg) / block -= peg – reach for that when you want the cut to happen no matter how peg was built.

Bonus: A Third Operation

There’s one more boolean operation worth knowing about: intersection(*shapes) keeps only the part where every shape overlaps – not everything combined (union), not one thing with pieces removed (difference), just the shared middle.

That comes out as a partial cylinder, sliced flat on one side. Shifting the box over means only part of the cylinder’s circular cross-section still overlaps it – the piece sticking out past the box’s edge is gone, along with the top and bottom the two shapes don’t share in z. intersection() keeps only what’s inside every shape at once, in every direction, not just height. It’s in the Cheatsheet and the Studio if you want to explore it further – this course doesn’t test you on it, since union() and difference() alone already cover almost everything you’ll want to build.

Checking Your Work

Exercise: build a block with a hole drilled through it. Use hole=True, or difference()/ -= directly -- whichever you like.

Match the Shape

One more, just for fun. Here’s a shape to reproduce. Flip to “Solution” to see it from any angle (spin it, zoom in), then flip back to “Your Code” and try to build the same thing. Flip back and forth as often as you want. “Check My Work” is loose on purpose here – it just checks that this generally looks like a table, not that it matches the solution exactly, so there’s more than one right answer.

Practice

That’s difference(), hole= as its shortcut, cutting in place with subtract()/-=, why hole=True doesn’t affect +/union(), and a peek at intersection(). Between this lesson and the last, you can now combine and cut shapes – everything you need to build genuinely complicated objects out of simple pieces.