Impossible Triangle¶
By the end of this lab you'll be able to:
- Draw a filled polygon from a hard-coded list of (x, y) waypoints
- Rotate a list of points around the center using
sinandcos - Explain how three shades of gray fake 3-D depth in an object that cannot exist
The Penrose triangle — three solid beams that each sit squarely in front of the next, all the way around. Follow any beam with your eye and the geometry works; look at the whole thing and it is impossible to build. The trick: one beam shape, drawn three times at 0°, 120°, and 240°, in three shades of gray that your brain reads as three-dimensional lighting.
Welcome to the Impossible Triangle!
Mathematician Roger Penrose called this "impossibility in its purest form."
Every corner makes sense on its own — but the whole object could never exist.
We'll build it from ONE list of five points and a rotation trick!
How It Works¶
The list beam holds five (x, y) waypoints outlining one L-shaped beam. The rotate() function spins a point around the center (0, 0) using the standard rotation formulas rx = x*cos(a) - y*sin(a) and ry = x*sin(a) + y*cos(a). A loop draws the beam three times — rotated by 0°, 120°, and 240° — filling each copy with a lighter or darker gray. Because the three shapes share edges perfectly, they weave into the famous impossible figure.
Sample Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
What Do You Think Will Happen?
The same five points are drawn three times, rotated by 0°, 120°, and 240°.
Will the three separate beams line up edge-to-edge into one closed triangle,
or will there be gaps between them? Guess, then click Run!
Try It Now¶
The three beams meet edge-to-edge with no gaps — and together they form an object that could never exist. Were you right?
How It Works¶
Each beam looks like a solid 3-D bar because of the shading: light gray reads as a surface facing the light, dark gray as a surface in shadow. At each corner, one beam's slanted cut makes it look like it slides behind its neighbor. Going around the triangle: the light beam covers the dark one, the medium covers the light, and the dark covers the medium. That circular chain of "in front of" can never happen with real objects — every beam would have to be in front of all the others at once.
Explanation Table¶
| Line | What it does |
|---|---|
beam = [(0, 76), (101, -99), ...] |
Five hard-coded waypoints outlining one L-shaped beam |
rx = x * math.cos(a) - y * math.sin(a) |
Rotation formula: spins a point around (0, 0) by angle a |
turned = [rotate(p, angle) for p in beam] |
Builds a new list with every waypoint rotated |
angle = i * 120 |
Three copies at 0°, 120°, 240° — perfect three-fold symmetry |
Learning Check¶
Find the Bug
In this version the triangle has fallen apart — three lonely beams float
with big gaps between them. One number in the final loop is wrong.
Hint: three copies must share 360° equally. Find it and fix it!
The bug is angle = i * 100 — the copies land at 0°, 100°, and 200°, leaving gaps. Three equal copies of anything need 360° ÷ 3 = 120° between them.
Experiments¶
-
Spin the whole figure. Change
angle = i * 120toangle = i * 120 + 60. You'll know it worked when the entire triangle rotates to point downward, still perfectly joined. -
Change the mood with color. Replace the shades list with
['#bcd4ec', '#5a8cc0', '#1e4a78']. You'll know it worked when the triangle turns three shades of blue and still looks 3-D. -
Flip the lighting. Reverse the shades to
['#505050', '#989898', '#d8d8d8']. You'll know it worked when the shadow appears to come from the opposite side — does the "in front" order look different? -
Break the illusion on purpose. Fill all three beams with the same shade,
'#989898'. You'll know it worked when the figure flattens into a plain 2-D triangle outline — proof that the shading, not the outline, fakes the 3-D. -
Drive Logo Colors. This same three-beam shape is also the basic outline of the logo used by a very large company's online file-storage and drive service — the kind of app millions of people use to save documents and photos in the cloud. Search online for that logo and find its three official RGB (or hex) color codes, then set
shadesto your findings, for exampleshades = ['#FFD14F', '#0EBC5F', '#2882FB']. You'll know it worked when your "impossible triangle" starts looking like a logo you've seen before! Special thanks to Sebastian B. for this fun addition.Show Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
import turtle import math monty = turtle.Turtle() monty.speed(0) monty.hideturtle() beam = [(0, 76), (101, -99), (137, -99), (154, -69), (36, 137)] shades = ['#FFD14F', '#0EBC5F', '#2882FB'] def rotate(point, angle): a = math.radians(angle) x = point[0] y = point[1] rx = x * math.cos(a) - y * math.sin(a) ry = x * math.sin(a) + y * math.cos(a) return (rx, ry) def draw_beam(points, color): monty.penup() monty.goto(points[0][0], points[0][1]) monty.pendown() monty.pencolor(color) monty.fillcolor(color) monty.pensize(2) monty.begin_fill() for p in points: monty.goto(p[0], p[1]) monty.goto(points[0][0], points[0][1]) monty.end_fill() for i in range(3): angle = i * 120 turned = [rotate(p, angle) for p in beam] draw_beam(turned, shades[i])
You Drew the Undrawable!
One point list, one rotation formula, three shades of gray —
and you built an object that cannot exist anywhere in the universe.
Up next: Concentric Ring Pulsation — rings of clashing colors that seem to vibrate.