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.