Monocurl Essays
Series Download

Why a cone is a third of a cylinder, and a sphere's volume

A cone holds exactly one third of the cylinder around it. A cube cut into three pyramids shows why, and the same slicing idea gives the volume of a sphere.

24 min·High school·

AssumesSimilar triangles and why area grows as the squareWhy the area of a circle is πr²

A cone full of water is emptied into a cylinder with the same base and the same height, three times. The third cone brings the water exactly to the brim.
Monocurl source
let BY = -1.75
let HH = 2.9
let RR = 1.2
let CX = -2.2
let KX = 1.2
let Pour = |u| {
    var f = 1 - (u - floor(u))
    if (u > 2.999) {
        f = 0
    }
    let g = f ^ (1 / 3)
    let lev = BY + HH * u / 3
    var parts = []
    if (f > 0.003) {
        parts .= fill{tint(AZURE, 0.6)} stroke{AZURE, 1.5} Polygon(flatten([[[CX, BY, 0]], ell([CX, BY + HH * g, 0], RR * g, PI, TAU)]))
        parts .= Lid([CX, BY + HH * g, 0], RR * g, AZURE, 0.35, 1.5)
    }
    if (u > 0.003) {
        parts .= Wall([KX, BY, 0], RR, [KX, lev, 0], RR, AZURE, 0.6, 1.5)
        parts .= Lid([KX, lev, 0], RR, AZURE, 0.35, 1.5)
    }
    parts .= center{[KX + 1.0, 1.9, 0]} scale{1.3} color{INK} Number(min(floor(u + 0.001), 3), 0)
    return parts
}
mesh back = [
    Path(ell([KX, BY, 0], RR, 0, PI), MIST, 2),
    Path(ell([KX, BY + HH, 0], RR, 0, PI), SLATE, 2.5),
    Path(ell([CX, BY + HH, 0], RR, 0, PI), SLATE, 2.5)
]
mesh water = Pour(u: 0)
mesh glass = [
    Path(flatten([[[KX - RR, BY + HH, 0]], ell([KX, BY, 0], RR, PI, TAU), [[KX + RR, BY + HH, 0]]]), INK, 3),
    Path(ell([KX, BY + HH, 0], RR, PI, TAU), INK, 3),
    Path([[CX - RR, BY + HH, 0], [CX, BY, 0], [CX + RR, BY + HH, 0]], INK, 3),
    Path(ell([CX, BY + HH, 0], RR, PI, TAU), INK, 3)
]
mesh marks = block {
    for (k in [1, 2]) {
        . Seg([KX + RR, BY + HH * k / 3, 0], [KX + RR + 0.18, BY + HH * k / 3, 0], SLATE, 2.5)
        . Name(str_join(["\frac{", to_string(k), "}{3}"]), [KX + RR + 0.5, BY + HH * k / 3, 0], 0.85, SLATE)
    }
    . center{[KX - 0.35, 1.9, 0]} Note("cones poured in", 0.76)
}

slide "pour"
    play Wait(1)
    water.u = 1
    play Lerp(1.9, [&water])
    play Wait(0.6)
    water.u = 2
    play Lerp(1.9, [&water])
    play Wait(0.6)
    water.u = 3
    play Lerp(1.9, [&water])
    play Wait(2.2)

Uses the shared definitions for this lesson's figures.

Take a cone and a cylinder with the same circular base and the same height, fill the cone with water and pour it into the cylinder. The water comes a third of the way up. A second cone brings it to two thirds, and the third fills the cylinder to the brim, with nothing left over. You can do this with paper models and rice, and it always comes out the same: three cones, not two and a half, not $\pi$.

A cylinder of radius $r$ and height $h$ has volume $\pi r^2 h$, the area of its base times its height. So the experiment says a cone has volume $\frac{1}{3}\pi r^2 h$. Where does a clean fraction like one third come from in a shape with a curved side and a sharp point?

The natural guess is one half

If you had to guess the fraction without the experiment, one half would be reasonable. Seen from the side, the cylinder is a rectangle and the cone is a triangle with the same base and height, and a triangle is half of its rectangle.

The experiment says the guess is wrong, and one slice shows why. Cut the cone and the cylinder with a horizontal plane halfway up.

A cone inside a cylinder, cut by a plane at half their height. The slice of the cone is a disc half as wide as the slice of the cylinder, so it has only a quarter of the area.
A cone inside a cylinder, cut by a plane at half their height. The slice of the cone is a disc half as wide as the slice of the cylinder, so it has only a quarter of the area.
Monocurl source
let BY = -1.6
let HH = 3.0
let RR = 1.4
let C = [-1.7, BY, 0]
let M = [-1.7, BY + HH / 2, 0]
let T = [-1.7, BY + HH, 0]
let V = [2.3, 0.75, 0]
mesh back = [Path(ell(C, RR, 0, PI), MIST, 2), Lid(T, RR, SLATE, 0.08, 2.5)]
mesh cone = Cone(C, RR, HH, AZURE, 0.3, 3)
mesh slice = [
    fill{alpha{0.3} EMBER} stroke{EMBER, 3} Polygon(ring(M, RR)),
    Lid(M, RR / 2, AZURE, 0.75, 3)
]
mesh front = [
    Path(flatten([[T - [RR, 0, 0]], ell(C, RR, PI, TAU), [T + [RR, 0, 0]]]), SLATE, 2.5),
    Seg(C + [RR + 0.25, 0, 0], C + [RR + 0.25, HH / 2, 0], INK, 2.5),
    Seg(C + [RR + 0.15, 0, 0], C + [RR + 0.35, 0, 0], INK, 2.5),
    Seg(C + [RR + 0.15, HH / 2, 0], C + [RR + 0.35, HH / 2, 0], INK, 2.5),
    Name("\tfrac{1}{2}h", C + [RR + 0.65, HH / 4, 0], 0.9)
]
mesh above = [
    center{V} fill{tint(EMBER, 0.3)} stroke{EMBER, 3} Circle(0.95, 96),
    center{V} fill{tint(AZURE, 0.75)} stroke{AZURE, 3} Circle(0.475, 96),
    center{[2.3, 1.95, 0]} Note("the two slices from above", 0.74),
    center{[2.3, -0.6, 0]} Cap("half the width", 0.78, AZURE),
    Name(str_join(["\left(\tfrac{1}{2}\right)^2 = \tfrac{1}{", to_string(2 * 2), "}"]), [2.3, -1.15, 0], 0.9, AZURE),
    center{[2.3, -1.7, 0]} Cap("of the area", 0.78, AZURE)
]

Uses the shared definitions for this lesson's figures.

Halfway up, the cone is half as wide as the cylinder. But the slice is a disc, and a disc half as wide has a quarter of the area, because scaling a figure by $k$ multiplies its area by $k^2$. The side view only sees one of the two directions in which the cone narrows. The cone loses material faster than the triangle suggests, so its share of the cylinder must be less than a half. That makes a third believable without explaining it.

A case that can be done exactly: three pyramids in a cube

A cone is hard to take apart, so start with a pointed solid that has flat sides. A pyramid is the solid made of all the segments from a point, its apex, to the points of a flat base. One pyramid whose volume needs no formula at all is hiding in a cube.

Pick one corner $A$ of a cube. Three of the cube’s faces meet at $A$, and the other three do not touch it. Join $A$ to every point of one of those three far faces, and you get a pyramid with a square base. Do the same for the other two far faces.

A cube is cut into three pyramids. Each has one face of the cube as its base and the same corner of the cube as its apex. The three pyramids are identical in shape, so each is one third of the cube.
Monocurl source
let a = 0.98
let A = [-a, a, a]
let BOT = [[-a, -a, -a], [a, -a, -a], [a, -a, a], [-a, -a, a]]
let RGT = [[a, -a, -a], [a, a, -a], [a, a, a], [a, -a, a]]
let BCK = [[-a, -a, -a], [a, -a, -a], [a, a, -a], [-a, a, -a]]
let pyramid = |base| [base, [A, base[0], base[1]], [A, base[1], base[2]], [A, base[2], base[3]], [A, base[3], base[0]]]
let HOME = aside(-1.25)
let Split = |u| [
    Solid(pyramid(BCK), PLUM, HOME + u * [-0.25, 0.3, -1.1]),
    Solid(pyramid(BOT), AZURE, HOME + u * [-0.4, -0.4, 0.65]),
    Solid(pyramid(RGT), EMBER, HOME + u * [1.1, 0, 0.25]),
    Pt(pr(A + HOME + u * [-0.4, -0.4, 0.65]), INK, 0.08)
]
mesh cube = Split(u: 0)
mesh labels = [
    center{[2.5, 1.3, 0]} Note("the cube", 0.76),
    Name("s^3", [2.5, 0.75, 0], 1.1),
    center{[2.5, -0.2, 0]} Note("each pyramid", 0.76),
    Name("\frac{1}{3}\,s^3", [2.5, -0.85, 0], 1.1, LEAF)
]

slide "split"
    play Wait(1.4)
    cube.u = 1
    play Lerp(2.8, [&cube])
    play Wait(2.4)
    cube.u = 0
    play Lerp(1.6, [&cube])
    play Wait(0.4)
    cube.u = 1
    play Lerp(1.6, [&cube])
    play Wait(2)

Uses the shared definitions for this lesson's figures.

Every point of the cube lies on a segment from $A$ to one of the three far faces, so the three pyramids fill the cube, and they overlap only along shared faces. They are also congruent to one another: turning the cube a third of a turn about its diagonal through $A$ carries each of the three far faces to the next, and so carries each pyramid to the next. Three identical pieces that make up a cube of side $s$ have volume $\frac{1}{3}s^3$ each.

Each of these pyramids has a square base of area $s^2$ and its apex at height $s$ above the base. So for this one shape,

$$ \text{volume} = \tfrac{1}{3} \cdot s^2 \cdot s = \tfrac{1}{3} \times \text{base area} \times \text{height}. $$

Pause and try

A cube of side $s$ can also be cut into six pyramids, by joining its center to each of its six faces. What are the base area and height of one of these pyramids, and what is its volume? Does “one third of base area times height” give the right answer for this shape too?

Show answerHide answer

Each pyramid has a face of the cube as its base, with area $s^2$, and its apex at the center of the cube, at height $\frac{s}{2}$ above the base. The six are congruent and fill the cube, so each has volume $\frac{1}{6}s^3$. The formula gives $\frac{1}{3} \cdot s^2 \cdot \frac{s}{2} = \frac{1}{6}s^3$, the same. The apex has moved from over a corner to over the middle, and the one third survives.

Sliding the slices: Cavalieri’s principle

Two examples from a cube are a long way from a cone. The pyramids so far have square bases, and their heights are tied to the size of the base. We need to know what happens to volume when the apex is moved, when the height is changed, and when the base is a different shape. One principle handles all three.

Think of a solid as a stack of thin slabs, like a deck of cards. Push the deck sideways so that it leans. Every card is still there and no card has changed, so the deck takes up the same amount of space as before.

A stepped pyramid of 12 square slabs with sides 12, 11, ..., 1 and thickness 1. Sliding the slabs sideways moves the apex from above the center of the base to beyond its edge. No slab changes, so the volume stays at 650 unit cubes.
Monocurl source
let n = 12
let W = 2.6
let d = 0.2
let HOME = aside(-1.75) + [0, -1.15, 0]
let face = |pts, amount| fill{tint(AZURE, amount)} stroke{AZURE, 1.5} Polygon(map(pts, |p| pr(p + HOME)))
let Stack = |s| block {
    for (k in range(0, n)) {
        let w = W * (1 - k / n)
        let off = aside(s * 0.62 * (W - w))
        let x0 = off[0] - w / 2
        let x1 = off[0] + w / 2
        let z0 = off[2] - w / 2
        let z1 = off[2] + w / 2
        let y0 = k * d
        let y1 = y0 + d
        . face([[x0, y1, z0], [x1, y1, z0], [x1, y1, z1], [x0, y1, z1]], 0.2)
        . face([[x0, y0, z1], [x1, y0, z1], [x1, y1, z1], [x0, y1, z1]], 0.42)
        . face([[x1, y0, z0], [x1, y0, z1], [x1, y1, z1], [x1, y1, z0]], 0.62)
    }
}
mesh stack = Stack(s: 0)
mesh labels = [
    center{[2.5, 1.3, 0]} Note("12 slabs, each 1 thick", 0.74),
    center{[2.5, 0.5, 0]} Note("volume in unit cubes", 0.74),
    Name(to_string(sum(map(range(1, n + 1), |k| k * k))), [2.5, -0.1, 0], 1.3, LEAF),
    center{[2.5, -0.9, 0]} Note("unchanged by sliding", 0.74)
]

slide "lean"
    play Wait(1.2)
    stack.s = 1
    play Lerp(2.6, [&stack])
    play Wait(1.4)
    stack.s = 0
    play Lerp(2, [&stack])
    play Wait(0.5)
    stack.s = 1
    play Lerp(2, [&stack])
    play Wait(1.8)

Uses the shared definitions for this lesson's figures.

With slabs of visible thickness the leaning stack is a staircase. Make the slabs thinner and more numerous and both stacks approach smooth pyramids, one upright and one leaning, while the argument stays the same. That suggests the following principle, named for Bonaventura Cavalieri, who published it in 1635.

I am going to use this without proving it, and you should know what is being left out. For solids made of finitely many slabs it is obvious, as with the cards. For solids with slanted or curved sides, a proof has to say what volume means, and the answer comes from integral calculus: the volume is the integral of the cross-sectional area over the height, so two solids with the same cross-sectional areas have the same volume. Note that the cross-sections need not have the same shape, only the same area, and that freedom is what we will use.

Here is what the principle buys. Take any pyramid or cone, with any flat base of area $B$ and with its apex at height $h$ above the plane of the base. Slice it parallel to the base at distance $t$ below the apex. The slice is a copy of the base scaled from the apex by the factor $t/h$, so by the square law for areas its area is

$$ B \left(\frac{t}{h}\right)^2. $$

This expression contains only $B$, $h$ and $t$. It does not know the shape of the base or where the apex sits above it. So any two cones or pyramids with the same base area and the same height have equal cross-sections at every level, and by Cavalieri’s principle they have the same volume. A cone of radius $r$ and height $h$ has the same volume as a square pyramid of height $h$ whose base has area $\pi r^2$.

Pause and try

A cone has base radius 6 and height 12. Find the areas of its cross-sections at distances $t = 3$, $6$ and $9$ below the apex, as multiples of $\pi$. A pyramid of height 12 has a square base of side $6\sqrt{\pi}$. What are its cross-sections at the same levels?

Show answerHide answer

The base area is $B = 36\pi$. At distance $t$ below the apex the slice has area $36\pi \cdot (t/12)^2$, which is $36\pi/16 = 2.25\pi$ at $t = 3$, then $36\pi/4 = 9\pi$ at $t = 6$, and $36\pi \cdot 9/16 = 20.25\pi$ at $t = 9$. The pyramid’s base has area $(6\sqrt{\pi})^2 = 36\pi$, the same $B$, and the same height, so its slices have the same areas: $2.25\pi$, $9\pi$ and $20.25\pi$. The slices are squares in one solid and discs in the other, with equal areas.

So the volume of a cone or pyramid depends only on $B$ and $h$, and the cube gave its value in one case. To find it for every $B$ and $h$ we can count slabs.

Counting the slabs

Cut the height of the cone into $n$ layers of equal thickness $h/n$, by planes parallel to the base. Number the cuts from the apex down: the $k$th cut is at distance $t = kh/n$ below the apex, where the cross-section has area $B(k/n)^2$.

Replace each layer by a slab with straight sides. If each slab is given the area of the cross-section at the bottom of its layer, the slabs stick out a little beyond the cone, and the stack is too big. Its volume is

$$ \frac{h}{n}\left[B\left(\frac{1}{n}\right)^2 + B\left(\frac{2}{n}\right)^2 + \dots + B\left(\frac{n}{n}\right)^2\right] = Bh \cdot \frac{1^2 + 2^2 + \dots + n^2}{n^3}. $$

So everything comes down to the sum of the first $n$ squares, compared with $n^3$.

Pause and try

Compute $\dfrac{1^2 + 2^2 + \dots + n^2}{n^3}$ for $n = 1$, $2$, $3$ and $4$. Is it heading toward $\frac{1}{2}$ or toward $\frac{1}{3}$?

Show answerHide answer

For $n = 1$: $1/1 = 1$. For $n = 2$: $5/8 = 0.625$. For $n = 3$: $14/27 \approx 0.519$. For $n = 4$: $30/64 \approx 0.469$. It is already below one half and still falling, which rules out $\frac{1}{2}$ as the place where it settles.

A cone enclosed in a stack of circular slabs, as the number of slabs grows from 4 to 48. The volumes of the stack around the cone and of a stack inside it, as fractions of the cylinder, close in on one third from above and below.
Monocurl source
let C = [-1.6, -1.55, 0]
let RR = 1.45
let HH = 3.0
let Cake = |n| {
    let m = to_int(round(n))
    let dh = HH / m
    var up = 0
    for (k in range(1, m + 1)) {
        up = up + k * k
    }
    let low = up - m * m
    return block {
        for (k in range(0, m)) {
            let r = RR * (1 - k / m)
            . Wall(C + [0, k * dh, 0], r, C + [0, (k + 1) * dh, 0], r, AZURE, 0.55, 1)
            . Lid(C + [0, (k + 1) * dh, 0], r, AZURE, 0.25, 1)
        }
        . center{[2.4, 1.2, 0]} scale{1.3} color{INK} Number(m, 0)
        . center{[2.4, 0.0, 0]} scale{1.3} color{EMBER} Number(up / m ^ 3, 4)
        . center{[2.4, -1.2, 0]} scale{1.3} color{PLUM} Number(low / m ^ 3, 4)
    }
}
mesh shell = [
    Path(ell(C, RR, 0, PI), MIST, 2),
    Path(flatten([[C + [-RR, HH, 0]], ell(C, RR, PI, TAU), [C + [RR, HH, 0]]]), SLATE, 2.5),
    Lid(C + [0, HH, 0], RR, SLATE, 0.06, 2.5)
]
mesh cake = Cake(n: 4)
mesh labels = [
    center{[2.4, 1.7, 0]} Note("slabs", 0.76),
    center{[2.4, 0.5, 0]} Cap("stack around the cone", 0.76, EMBER),
    center{[2.4, -0.7, 0]} Cap("stack inside the cone", 0.76, PLUM),
    center{[2.4, -1.85, 0]} Note("as fractions of the cylinder", 0.72)
]

slide "refine"
    play Wait(1.4)
    cake.n = 48
    play Lerp(6.5, [&cake], |u| u ^ 2)
    play Wait(2.2)

Uses the shared definitions for this lesson's figures.

The numbers go to one third. To prove it we need the sum of squares in closed form:

$$ 1^2 + 2^2 + \dots + n^2 = \frac{n(n+1)(2n+1)}{6}. $$

For $n = 4$ this gives $\frac{4 \cdot 5 \cdot 9}{6} = 30$, which matches $1 + 4 + 9 + 16$. A proof of the formula is one of the problems at the end. Dividing by $n^3$, and sharing the three factors of $n$ among the three factors on top,

$$ \frac{1^2 + 2^2 + \dots + n^2}{n^3} = \frac{1}{6}\left(1 + \frac{1}{n}\right)\left(2 + \frac{1}{n}\right). $$

As $n$ grows, $\frac{1}{n}$ shrinks toward zero and the right side closes in on $\frac{1}{6} \cdot 1 \cdot 2 = \frac{1}{3}$. The 3 in the cone formula is the 3 in “the sum of the first $n$ squares is about $\frac{1}{3}n^3$”.

The proof is the animation written down: the upper bound is the stack around the cone and the lower bound is the stack inside it. It is the same trap that caught the area of a circle between two polygons. Besides Cavalieri’s principle, it rests on the square law for the areas of the slices and on the idea of a quantity closing in on a limit.

The result agrees with the cube: for $B = s^2$ and $h = s$ it gives $\frac{1}{3}s^3$. It also explains the failed guess. In the plane, a triangle’s slices have lengths that grow in proportion to $t$, and $\frac{1 + 2 + \dots + n}{n^2}$ closes in on $\frac{1}{2}$. In space the slices have areas that grow as $t^2$, and the fraction becomes $\frac{1}{3}$.

The sphere

A sphere has no flat base and no apex, so the cone formula does not apply to it. But Cavalieri’s principle does not care about apexes. If we can find a solid we understand whose slices have the same areas as the slices of a ball, we are done.

By symmetry it is enough to treat half a ball. Take a ball of radius 5 and cut it in half through its center, and stand the half on its flat face, like a dome. Slice the dome at height $y$ above that face.

Pause and try

For a dome of radius 5, find the area of the slice at height $y = 3$ and at height $y = 4$, as multiples of $\pi$. (Each slice is a disc. A point on its edge is at distance 5 from the center of the ball.) Then compare each with $25\pi - \pi y^2$.

Show answerHide answer

Let $x$ be the radius of the slice. The center of the ball, the center of the slice and a point on the edge of the slice form a right triangle with legs $y$ and $x$ and hypotenuse 5. At $y = 3$: $x^2 = 25 - 9 = 16$, so the area is $16\pi$. At $y = 4$: $x^2 = 25 - 16 = 9$, so the area is $9\pi$. And $25\pi - 9\pi = 16\pi$, $25\pi - 16\pi = 9\pi$. The slice at height $y$ has area $25\pi - \pi y^2$ exactly.

The expression $25\pi - \pi y^2$ is a difference of two areas we recognize. The first, $25\pi$, is the area of a disc of radius 5, the slice of a cylinder of radius 5 at every height. The second, $\pi y^2$, is the area of a disc of radius $y$, and a solid whose slice at height $y$ has radius $y$ is a cone as wide as it is tall, standing on its point. So the dome’s slices match those of a cylinder with a cone removed.

  1. A dome, half of a ball of radius r, and beside it a cylinder of radius r and height r from which a cone has been hollowed out, point down.
  2. Slice both at the same height y. The dome gives a disc and the other solid gives a ring. Their true shapes are drawn below.
  3. In the dome, the radius x of the disc, the height y and the radius r of the ball form a right triangle. So x² = r² − y², and the disc has area π(r² − y²).
  4. The cone is as wide as it is tall, so at height y the hole in the ring has radius y. The ring has area πr² − πy², the same as the disc.
  5. Move the slice up and down. At every height the two areas agree.
A dome of radius $r$, and a cylinder of radius $r$ and height $r$ with a cone hollowed out of it, sliced at the same height. The disc from the dome and the ring from the cylinder have the same area at every height. Areas are shown for $r = 5$.
Monocurl source
let r = 1.3
let BY = 0.3
let DX = -2.0
let KX = 1.75
let top = BY + r * CT
let lip = arcsin(ST / CT)
let Slices = |t| {
    let y = t * r
    let x = sqrt(r * r - y * y)
    let lev = BY + y * CT
    return [
        Lid([DX, lev, 0], x, AZURE, 0.65, 2.5),
        Lid([KX, lev, 0], r, EMBER, 0.6, 2.5),
        fill{tint(SLATE, 0.1)} stroke{EMBER, 2} Polygon(ring([KX, lev, 0], max(y, 0.02))),
        center{[DX - 0.75, -1.25, 0]} fill{tint(AZURE, 0.65)} stroke{AZURE, 2.5} Circle(0.5 * x, 64),
        center{[KX - 0.75, -1.25, 0]} fill{tint(EMBER, 0.6)} stroke{EMBER, 2.5} Circle(0.5 * r, 64),
        center{[KX - 0.75, -1.25, 0]} fill{PAPER} stroke{EMBER, 2} Circle(max(0.5 * y, 0.01), 64),
        center{[DX + 0.8, -1.5, 0]} scale{1.25} color{AZURE} Number(PI * (25 - 25 * t * t), 1),
        center{[KX + 0.8, -1.5, 0]} scale{1.25} color{EMBER} Number(PI * 25 - PI * 25 * t * t, 1),
        center{[-0.12, -1.5, 0]} scale{1.25} color{INK} Number(5 * t, 1)
    ]
}
mesh solids = [
    Path(ell([DX, BY, 0], r, 0, PI), MIST, 2),
    fill{tint(AZURE, 0.14)} stroke{AZURE, 3} Polygon(flatten([
        map(sample(0, PI, 48), |a| [DX + r * cos(a), BY + r * sin(a), 0]),
        ell([DX, BY, 0], r, PI, TAU)
    ])),
    Path(ell([KX, BY, 0], r, 0, PI), MIST, 2),
    Wall([KX, BY, 0], r, [KX, top, 0], r, EMBER, 0.14, 3),
    Lid([KX, top, 0], r, SLATE, 0.1, 3),
    Path([
        [KX - r * cos(lip), top - r * ST * sin(lip), 0],
        [KX, BY, 0],
        [KX + r * cos(lip), top - r * ST * sin(lip), 0]
    ], SLATE, 2.5)
]
mesh slices = []
mesh tri = []
mesh labels = [
    center{[DX, -0.95, 0]} Cap("half a ball", 0.95, AZURE),
    center{[KX, -0.95, 0]} Cap("cylinder minus cone", 0.95, EMBER),
    Name("\text{radius } r", [DX, -1.6, 0], 0.95, SLATE),
    Name("\text{radius } r,\ \text{height } r", [KX, -1.6, 0], 0.95, SLATE)
]

slide "A dome, half of a ball of radius r, and beside it a cylinder of radius r and height r from which a cone has been hollowed out, point down."
    play Fade(0.7)

slide "Slice both at the same height y. The dome gives a disc and the other solid gives a ring. Their true shapes are drawn below."
    labels = []
    play Fade(0.3, [&labels])
    slices = Slices(t: 0.6)
    labels = [
        center{[DX + 0.8, -1.0, 0]} Note("area", 0.74),
        center{[KX + 0.8, -1.0, 0]} Note("area", 0.74),
        center{[-0.12, -1.0, 0]} Note("height y", 0.74)
    ]
    play Fade(0.7)

slide "In the dome, the radius x of the disc, the height y and the radius r of the ball form a right triangle. So x² = r² − y², and the disc has area π(r² − y²)."
    tri = [
        Path([[DX, BY, 0], [DX, BY + 0.6 * r * CT, 0], [DX + 0.8 * r, BY + 0.6 * r * CT, 0]], INK, 3),
        Seg([DX, BY, 0], [DX + 0.8 * r, BY + 0.6 * r * CT, 0], LEAF, 3.5),
        Name("y", [DX - 0.2, BY + 0.3 * r * CT, 0], 0.85),
        Name("x", [DX + 0.4 * r, BY + 0.6 * r * CT + 0.22, 0], 0.85),
        Name("r", [DX + 0.55 * r, BY + 0.2 * r * CT, 0], 0.85, LEAF)
    ]
    play Fade(0.6, [&tri])

slide "The cone is as wide as it is tall, so at height y the hole in the ring has radius y. The ring has area πr² − πy², the same as the disc."
    tri .= Path([[KX, BY, 0], [KX, BY + 0.6 * r * CT, 0], [KX + 0.6 * r, BY + 0.6 * r * CT, 0]], INK, 3)
    tri .= Name("y", [KX - 0.2, BY + 0.3 * r * CT, 0], 0.85)
    tri .= Name("y", [KX + 0.3 * r, BY + 0.6 * r * CT + 0.22, 0], 0.85)
    play Fade(0.6, [&tri])

slide "Move the slice up and down. At every height the two areas agree."
    tri = []
    play Fade(0.4, [&tri])
    slices.t = 0.12
    play Lerp(2, [&slices])
    slices.t = 0.93
    play Lerp(3, [&slices])
    slices.t = 0.6
    play Lerp(1.6, [&slices])

Uses the shared definitions for this lesson's figures.

Now the volumes. The cylinder has volume $\pi r^2 \cdot r = \pi r^3$, and the cone, with the same base and height, has $\frac{1}{3}\pi r^3$. So the cylinder with the cone removed has volume $\frac{2}{3}\pi r^3$, and the dome, having the same slices, has the same volume. A whole ball is two domes.

The proof is complete given the two results it uses, Cavalieri’s principle and the volume of a cone. The theorem is due to Archimedes, who found it in the third century BC by a related route, balancing slices of a sphere, a cone and a cylinder against one another. For a ball inside the cylinder that just contains it, of radius $r$ and height $2r$, it says the ball fills exactly two thirds of the cylinder, and by ancient accounts a sphere and a cylinder were carved on his tomb.

A cone, a ball and a cylinder, all of radius r and height 2r. Their volumes are \frac{2}{3}\pi r^3, \frac{4}{3}\pi r^3 and 2\pi r^3, in the ratio 1 to 2 to 3.
A cone, a ball and a cylinder, all of radius $r$ and height $2r$. Their volumes are $\frac{2}{3}\pi r^3$, $\frac{4}{3}\pi r^3$ and $2\pi r^3$, in the ratio 1 to 2 to 3.
Monocurl source
let r = 1.0
let BY = -0.45
let HH = 2 * r * CT
let XS = [-2.4, 0, 2.4]
mesh cone = [
    Path(ell([XS[0], BY, 0], r, 0, PI), MIST, 2),
    Cone([XS[0], BY, 0], r, HH, AZURE, 0.3, 3)
]
mesh ball = [
    center{[XS[1], BY + HH / 2, 0]} fill{tint(PLUM, 0.25)} stroke{PLUM, 3} Circle(r, 96),
    Path(ell([XS[1], BY + HH / 2, 0], r, 0, PI), tint(PLUM, 0.5), 2),
    Path(ell([XS[1], BY + HH / 2, 0], r, PI, TAU), PLUM, 2.5),
    Seg([XS[1], BY + HH / 2, 0], [XS[1] + r, BY + HH / 2, 0], INK, 2.5),
    Name("r", [XS[1] + 0.5, BY + HH / 2 + 0.22, 0], 0.85)
]
mesh can = [
    Path(ell([XS[2], BY, 0], r, 0, PI), MIST, 2),
    Wall([XS[2], BY, 0], r, [XS[2], BY + HH, 0], r, EMBER, 0.3, 3),
    Lid([XS[2], BY + HH, 0], r, EMBER, 0.14, 3)
]
mesh measure = [
    Seg([-1.15, BY, 0], [-1.15, BY + HH, 0], INK, 2.5),
    Seg([-1.25, BY, 0], [-1.05, BY, 0], INK, 2.5),
    Seg([-1.25, BY + HH, 0], [-1.05, BY + HH, 0], INK, 2.5),
    Name("2r", [-1.5, BY + 0.72 * HH, 0], 0.85)
]
mesh labels = [
    Name("\frac{2}{3}\pi r^3", [XS[0], -1.3, 0], 0.85, AZURE),
    Name("\frac{4}{3}\pi r^3", [XS[1], -1.3, 0], 0.85, PLUM),
    Name("2\pi r^3", [XS[2], -1.3, 0], 0.95, EMBER),
    Name("1", [XS[0], -1.95, 0], 1.1, LEAF),
    Name(":", [-1.2, -1.95, 0], 1.1, LEAF),
    Name("2", [XS[1], -1.95, 0], 1.1, LEAF),
    Name(":", [1.2, -1.95, 0], 1.1, LEAF),
    Name("3", [XS[2], -1.95, 0], 1.1, LEAF)
]

Uses the shared definitions for this lesson's figures.

Where the one third stops

The factor $\frac{1}{3}$ belongs to solids that taper to a point along straight lines, so that the slice at distance $t$ from the apex is a scaled copy of the base with area proportional to $t^2$. Change the way the solid tapers and the fraction changes. The dome is an example: it also narrows from a disc of radius $r$ to a point over a height $r$, and it fills two thirds of its cylinder, twice what the cone fills, because it bulges where the cone is straight.

A cone with its tip cut off has two faces of different sizes, and its volume is found by subtracting the missing tip from the whole cone, as in one of the problems below.

Cavalieri’s principle has its own conditions: the slices must be taken by parallel planes at the same heights in both solids, and it is their areas that must agree. Equal widths are not enough, as the cone and its side-view triangle showed.

Looking back

The obstacle was that there is no evident way to cut a cone into pieces that reassemble into a box. Two ideas got around it. The first was to compare slices instead of shapes: two solids with equal slices at every height have equal volume. That reduced every cone and pyramid to a single question about slices whose areas grow as a square. The second was to answer that question by trapping the volume between two stacks of slabs, which turned geometry into a statement about $1^2 + 2^2 + \dots + n^2$.

Both ideas are the beginning of integral calculus, where “volume is the sum of the slices” becomes a definition and sums like the one above are computed once and for all.

Check yourself

A cone and a cylinder have the same base and the same height. The cylinder holds 600 mL. How much does the cone hold?

Problems

Problem 1

Find the volume of a cone with base radius 6 and height 4.

Show solutionHide solution

$V = \frac{1}{3}\pi r^2 h = \frac{1}{3}\pi \cdot 36 \cdot 4 = 48\pi \approx 150.8$.

Problem 2

A pyramid has a square base of side 6. Each of its four triangular faces has height 5, measured from the middle of a base edge up to the apex, which is above the center of the base. Find the volume of the pyramid.

Show solutionHide solution

The height of the pyramid is the perpendicular distance from the apex to the base, which is not given. The center of the base, the midpoint of a base edge and the apex form a right triangle. One leg runs from the center to the middle of an edge and has length $6/2 = 3$. The hypotenuse is the height of a triangular face, 5. The other leg is the height $h$ of the pyramid, so $h = \sqrt{5^2 - 3^2} = 4$. Then $V = \frac{1}{3} \cdot 6^2 \cdot 4 = 48$.

Problem 3

A bowl has the shape of half a ball of radius 9 cm. How many liters does it hold? (One liter is 1000 cm³.)

Show solutionHide solution

Half of $\frac{4}{3}\pi r^3$ is $\frac{2}{3}\pi r^3 = \frac{2}{3}\pi \cdot 729 = 486\pi \approx 1526.8$ cm³, which is about 1.53 liters.

Problem 4

A conical glass, point down, is filled with water to half its depth. (a) What fraction of the glass’s full volume is the water? (b) To what fraction of the depth must it be filled to be half full?

Show solutionHide solution

(a) The water forms a cone that is a scaled copy of the whole glass, with scale factor $\frac{1}{2}$, since it shares the apex and both its depth and its radius are half as large. Scaling by $k$ multiplies volume by $k^3$, so the water is $\left(\frac{1}{2}\right)^3 = \frac{1}{8}$ of the glass. Check with the formula: $\frac{1}{3}\pi (r/2)^2 (h/2) = \frac{1}{8} \cdot \frac{1}{3}\pi r^2 h$.

(b) If the water reaches a fraction $k$ of the depth, its volume is $k^3$ of the glass. We need $k^3 = \frac{1}{2}$, so $k = \sqrt[3]{1/2} \approx 0.794$. The glass is half full when the water is about 79% of the way up. Check: $0.794^3 \approx 0.5006$.

Problem 5

For a cone of base area $B$ and height $h$, compute by hand the volume of the stack of 4 slabs around the cone and of the stack of 4 slabs inside it, as multiples of $Bh$. Check that $\frac{1}{3}$ lies between them, and explain why the two stacks differ by exactly $\frac{1}{4}Bh$.

Show solutionHide solution

Each slab has thickness $h/4$. The cross-sections at the four cuts, at distances $\frac{h}{4}, \frac{2h}{4}, \frac{3h}{4}, h$ from the apex, have areas $\frac{1}{16}B$, $\frac{4}{16}B$, $\frac{9}{16}B$ and $\frac{16}{16}B$. The outer stack uses all four:

$$ \frac{h}{4} \cdot \frac{B}{16}(1 + 4 + 9 + 16) = \frac{30}{64}Bh \approx 0.469\,Bh. $$

The inner stack gives each layer the area at its top, so it uses areas $0$, $\frac{1}{16}B$, $\frac{4}{16}B$, $\frac{9}{16}B$:

$$ \frac{h}{4} \cdot \frac{B}{16}(0 + 1 + 4 + 9) = \frac{14}{64}Bh \approx 0.219\,Bh. $$

And $0.219 < 0.333 < 0.469$. The two sums contain the same terms except that the outer one has the largest slab, of area $B$ and thickness $\frac{h}{4}$, and the inner one has a slab of area 0 in its place. So they differ by $\frac{1}{4}Bh$. With $n$ slabs the difference is $\frac{1}{n}Bh$ for the same reason, which is why the trap closes.

Problem 6

Prove that $1^2 + 2^2 + \dots + n^2 = \dfrac{n(n+1)(2n+1)}{6}$, as follows. (a) Check that $(k+1)^3 - k^3 = 3k^2 + 3k + 1$. (b) Add this identity for $k = 1, 2, \dots, n$ and observe what happens on the left side. (c) Solve for the sum of squares, using $1 + 2 + \dots + n = \frac{n(n+1)}{2}$.

Show solutionHide solution

(a) $(k+1)^3 = k^3 + 3k^2 + 3k + 1$, and subtracting $k^3$ leaves $3k^2 + 3k + 1$.

(b) On the left the sum is $(2^3 - 1^3) + (3^3 - 2^3) + \dots + \left((n+1)^3 - n^3\right)$. Each cube appears once with a plus sign and once with a minus sign, except the first and the last, so the left side is $(n+1)^3 - 1$. Writing $S$ for $1^2 + 2^2 + \dots + n^2$, the right side is $3S + 3 \cdot \frac{n(n+1)}{2} + n$.

(c) So $3S = (n+1)^3 - 1 - n - \frac{3n(n+1)}{2} = (n+1)^3 - (n+1) - \frac{3n(n+1)}{2}$. Factor out $(n+1)$:

$$ 3S = (n+1)\left[(n+1)^2 - 1 - \tfrac{3n}{2}\right] = (n+1)\left[n^2 + \tfrac{n}{2}\right] = \frac{n(n+1)(2n+1)}{2}. $$

Dividing by 3 gives $S = \frac{n(n+1)(2n+1)}{6}$. Check with $n = 3$: $\frac{3 \cdot 4 \cdot 7}{6} = 14 = 1 + 4 + 9$.

A cone of base radius 6 and height 12 is cut by a plane parallel to its base, halfway up. The tip that is removed is a cone of radius 3 and height 6.
A cone of base radius 6 and height 12 is cut by a plane parallel to its base, halfway up. The tip that is removed is a cone of radius 3 and height 6.
Monocurl source
let C = [-1.5, -1.7, 0]
let RR = 1.5
let HH = 3.3
let M = C + [0, HH / 2, 0]
mesh back = Path(ell(C, RR, 0, PI), MIST, 2)
mesh whole = Cone(C, RR, HH, AZURE, 0.4, 3)
mesh tip = [Cone(M, RR / 2, HH / 2, SLATE, 0.12, 2.5), Lid(M, RR / 2, AZURE, 0.18, 3)]
mesh dims = [
    Seg(C, C + [RR, 0, 0], INK, 2.5),
    Name("6", C + [RR / 2, 0.2, 0], 0.85),
    Seg(M, M + [RR / 2, 0, 0], INK, 2.5),
    Name("3", M + [-0.2, 0, 0], 0.85),
    Seg(C + [RR + 0.4, 0, 0], C + [RR + 0.4, HH, 0], INK, 2.5),
    Seg(C + [RR + 0.3, 0, 0], C + [RR + 0.5, 0, 0], INK, 2.5),
    Seg(C + [RR + 0.3, HH / 2, 0], C + [RR + 0.5, HH / 2, 0], INK, 2.5),
    Seg(C + [RR + 0.3, HH, 0], C + [RR + 0.5, HH, 0], INK, 2.5),
    Name("6", C + [RR + 0.7, HH / 4, 0], 0.85),
    Name("6", C + [RR + 0.7, 3 * HH / 4, 0], 0.85),
    center{[2.5, 1.0, 0]} Note("the whole cone", 0.76),
    Name("r = 6,\ h = 12", [2.5, 0.5, 0], 0.85),
    center{[2.5, -0.4, 0]} Note("the tip removed", 0.76),
    Name("r = 3,\ h = 6", [2.5, -0.9, 0], 0.85)
]

Uses the shared definitions for this lesson's figures.

Problem 7

The figure above shows a cone of base radius 6 and height 12 cut by a plane parallel to its base, halfway up. Find the volume of the lower piece. What fraction of the original cone is it?

Show solutionHide solution

The lower piece is the whole cone with the tip removed. The whole cone has volume $\frac{1}{3}\pi \cdot 6^2 \cdot 12 = 144\pi$. The tip is a cone with apex at the same point, height 6 and radius 3 (half of each, since it is the whole cone scaled by $\frac{1}{2}$), so its volume is $\frac{1}{3}\pi \cdot 3^2 \cdot 6 = 18\pi$. The lower piece has volume $144\pi - 18\pi = 126\pi \approx 395.8$. The tip is $\frac{18}{144} = \frac{1}{8}$ of the cone, as the cube law for scaling predicts, so the lower piece is $\frac{7}{8}$ of it.

Problem 8

A ball of radius $r$ is cut by a plane at distance $r - a$ from its center, where $0 < a \le r$. The smaller piece is called a cap of height $a$. Use the comparison of the dome with the cylinder minus a cone to show that the cap has volume $\dfrac{\pi a^2 (3r - a)}{3}$. Check the formula for $a = r$, and evaluate it for $r = 5$, $a = 2$.

Show solutionHide solution

Stand the half ball on its flat face. The cap is the part of it between heights $r - a$ and $r$. At every height the half ball has the same cross-sectional area as the cylinder with the cone removed, so by Cavalieri’s principle, applied between the planes at heights $r - a$ and $r$, the cap has the same volume as the part of that solid between the same two heights.

That part is a slab of the cylinder, of volume $\pi r^2 a$, minus the part of the cone between heights $r - a$ and $r$. The cone has its apex at height 0 and radius equal to its height. Up to height $r$ it has volume $\frac{1}{3}\pi r^3$, and up to height $r - a$ it has volume $\frac{1}{3}\pi (r - a)^3$. So

$$ \text{cap} = \pi r^2 a - \tfrac{1}{3}\pi\left[r^3 - (r - a)^3\right]. $$

Expanding, $r^3 - (r - a)^3 = 3r^2 a - 3ra^2 + a^3$, so

$$ \text{cap} = \pi r^2 a - \pi r^2 a + \pi r a^2 - \tfrac{1}{3}\pi a^3 = \pi a^2\left(r - \tfrac{a}{3}\right) = \frac{\pi a^2(3r - a)}{3}. $$

For $a = r$ the cap is the half ball, and the formula gives $\frac{\pi r^2 \cdot 2r}{3} = \frac{2}{3}\pi r^3$, as it should. For $r = 5$ and $a = 2$ it gives $\frac{\pi \cdot 4 \cdot 13}{3} = \frac{52\pi}{3} \approx 54.5$.

Shared definitions used by this lesson's figures
# house kit: prepended to every essay figure after the std imports

# palette. AZURE and EMBER are the two actors, LEAF marks an answer, ROSE a problem
let PAPER = [1, 1, 1, 1]
let INK = [0.08, 0.09, 0.11, 1]
let SLATE = [0.40, 0.44, 0.50, 1]
let MIST = [0.85, 0.86, 0.88, 1]
let AZURE = [0.13, 0.42, 0.68, 1]
let EMBER = [0.89, 0.42, 0.12, 1]
let LEAF = [0.13, 0.55, 0.36, 1]
let ROSE = [0.78, 0.22, 0.24, 1]
let PLUM = [0.47, 0.30, 0.66, 1]
let GOLD = [0.85, 0.62, 0.08, 1]

background = PAPER

# an opaque pastel of col; use for fills so overlaps do not darken
let tint = |col, amount = 0.18| [
    1 - (1 - col[0]) * amount,
    1 - (1 - col[1]) * amount,
    1 - (1 - col[2]) * amount,
    1
]

# text: Cap for labels, Note for quiet labels, Math for typeset maths
let Cap = |txt, size = 0.75, col = INK| color{col} Text(txt, size, "Charter")
let Note = |txt, size = 0.65| color{SLATE} Text(txt, size, "Charter")
let Math = |tex, size = 0.9, col = INK| color{col} Tex(tex, size)

# a paper rectangle to sit behind text that crosses lines
let Plate = |pos, size| center{pos} fill{PAPER} stroke{alpha{0} PAPER, 0} Rect(size)

# shapes with fill and stroke both set, so no stray black appears
let Pt = |pos, col = INK, r = 0.075| center{pos} fill{col} stroke{col, 1} Circle(r, 48)
let Ring = |pos, col = INK, r = 0.1, w = 3| center{pos} fill{PAPER} stroke{col, w} Circle(r, 48)
let Seg = |a, b, col = INK, w = 3| stroke{col, w} Line(a, b)
let Path = |pts, col = INK, w = 3| stroke{col, w} Polyline(pts)
let Region = |pts, col| fill{col} stroke{alpha{0} col, 0} Polygon(pts)
let Outline = |pts, col = INK, w = 3| fill{alpha{0} PAPER} stroke{col, w} Polygon(pts)
let Shape = |pts, col, amount = 0.18, w = 3| fill{tint(col, amount)} stroke{col, w} Polygon(pts)
let Disc = |pos, r, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Circle(r, 96)
let Box = |pos, size, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Rect(size)
# a line from a to b ending in a small solid arrowhead
let Tip = |a, b, col = INK, w = 3, head = 0.17| {
    let d = normalize([b[0] - a[0], b[1] - a[1], 0])
    let n = [-d[1], d[0], 0]
    let base = [b[0] - d[0] * head, b[1] - d[1] * head, 0]
    return [
        stroke{col, w} Line(a, base),
        fill{col} stroke{col, 1} Polygon([
            b,
            [base[0] + n[0] * head * 0.42, base[1] + n[1] * head * 0.42, 0],
            [base[0] - n[0] * head * 0.42, base[1] - n[1] * head * 0.42, 0]
        ])
    ]
}

# plots. a frame is [x0, x1, y0, y1, centre, width, height]: a data window and the scene box it fills
let Frame = |x0, x1, y0, y1, c = [0, 0, 0], w = 6.4, h = 3.6| [x0, x1, y0, y1, c, w, h]
let fx = |fr, x| fr[4][0] + (x - (fr[0] + fr[1]) / 2) * fr[5] / (fr[1] - fr[0])
let fy = |fr, y| fr[4][1] + (y - (fr[2] + fr[3]) / 2) * fr[6] / (fr[3] - fr[2])
let at = |fr, x, y| [fx(fr, x), fy(fr, y), 0]

# axes through the data origin (or the nearest edge of the window), with optional names
let Axes = |fr, x_name = "", y_name = "", col = SLATE| {
    let ox = clamp(fr[0], 0, fr[1])
    let oy = clamp(fr[2], 0, fr[3])
    var parts = [
        Tip(at(fr, fr[0], oy), [fx(fr, fr[1]) + 0.25, fy(fr, oy), 0], col, 2.5, 0.15),
        Tip(at(fr, ox, fr[2]), [fx(fr, ox), fy(fr, fr[3]) + 0.25, 0], col, 2.5, 0.15)
    ]
    if (x_name != "") {
        parts .= center{[fx(fr, fr[1]) + 0.5, fy(fr, oy), 0]} Math(x_name, 0.8, col)
    }
    if (y_name != "") {
        parts .= center{[fx(fr, ox), fy(fr, fr[3]) + 0.5, 0]} Math(y_name, 0.8, col)
    }
    return parts
}

# tick marks with numbers at the listed data values
let XTicks = |fr, xs, col = SLATE, places = 0| block {
    let oy = fy(fr, clamp(fr[2], 0, fr[3]))
    for (x in xs) {
        . Seg([fx(fr, x), oy - 0.07, 0], [fx(fr, x), oy + 0.07, 0], col, 2)
        . center{[fx(fr, x), oy - 0.33, 0]} Math(to_string(x, places), 0.72, col)
    }
}
let YTicks = |fr, ys, col = SLATE, places = 0| block {
    let ox = fx(fr, clamp(fr[0], 0, fr[1]))
    for (y in ys) {
        . Seg([ox - 0.07, fy(fr, y), 0], [ox + 0.07, fy(fr, y), 0], col, 2)
        . center{[ox - 0.36, fy(fr, y), 0]} Math(to_string(y, places), 0.72, col)
    }
}

# faint grid lines at the listed data values
let GridLines = |fr, xs, ys, col = MIST| block {
    for (x in xs) {
        . Seg(at(fr, x, fr[2]), at(fr, x, fr[3]), col, 1.5)
    }
    for (y in ys) {
        . Seg(at(fr, fr[0], y), at(fr, fr[1], y), col, 1.5)
    }
}

# the graph of f over [a, b], drawn in the frame. values are clamped to the window
let Graph = |fr, f, a, b, col = AZURE, w = 4, n = 160|
    stroke{col, w} Polyline(map(sample(a, b, n), |x| at(fr, x, clamp(fr[2], f(x), fr[3]))))

# the region between the graph of f and the x axis over [a, b]
let AreaUnder = |fr, f, a, b, col = AZURE, amount = 0.2, n = 80| {
    var pts = [at(fr, a, 0)]
    for (x in sample(a, b, n)) {
        pts .= at(fr, x, clamp(fr[2], f(x), fr[3]))
    }
    pts .= at(fr, b, 0)
    return fill{tint(col, amount)} stroke{alpha{0} col, 0} Polygon(pts)
}

let rad = |d| d * PI / 180
let Name = |txt, pos, size = 0.85, col = INK| center{pos} Math(txt, size, col)
# a view from the front, a little to the right and above. y is up and z points at the viewer
let YAW = rad(-32)
let TILT = rad(20)
let ST = sin(TILT)
let CT = cos(TILT)
let turned = |p| [p[0] * cos(YAW) + p[2] * sin(YAW), p[1], p[2] * cos(YAW) - p[0] * sin(YAW)]
let pr = |p| [turned(p)[0], turned(p)[1] * CT - turned(p)[2] * ST, 0]
let toward = |v| turned(v)[1] * ST + turned(v)[2] * CT
# the world vector that moves a drawing d to the right on screen
let aside = |d| [d * cos(YAW), 0, d * sin(YAW)]
# the faces of a convex solid that the viewer can see, shaded by how they face the light
let Solid = |faces, col, move = [0, 0, 0], w = 2.5| {
    var total = [0, 0, 0]
    var count = 0
    for (f in faces) {
        for (v in f) {
            total = total + v
            count = count + 1
        }
    }
    let mid = (1 / count) * total
    let light = normalize([-0.5, 0.75, 0.45])
    return block {
        for (f in faces) {
            var fc = [0, 0, 0]
            for (v in f) {
                fc = fc + v
            }
            fc = (1 / len(f)) * fc
            var nrm = normalize(cross(f[1] - f[0], f[2] - f[0]))
            if (dot(nrm, fc - mid) < 0) {
                nrm = -1 * nrm
            }
            if (toward(nrm) > 0.001) {
                . fill{tint(col, 0.55 - 0.3 * dot(nrm, light))} stroke{col, w} Polygon(map(f, |v| pr(v + move)))
            }
        }
    }
}
# a horizontal circle of radius r seen in this view, centered at the screen point c.
# angles from PI to TAU run along the near half
let ell = |c, r, a0, a1, n = 40| map(sample(a0, a1, n), |a| [c[0] + r * cos(a), c[1] + r * ST * sin(a), 0])
let ring = |c, r| map(sample_clopen(0, TAU, 64), |a| [c[0] + r * cos(a), c[1] + r * ST * sin(a), 0])
let Lid = |c, r, col, amount = 0.2, w = 2.5| fill{tint(col, amount)} stroke{col, w} Polygon(ring(c, r))
# the curved wall between two horizontal circles
let Wall = |c0, r0, c1, r1, col, amount = 0.4, w = 2.5| fill{tint(col, amount)} stroke{col, w}
    Polygon(flatten([ell(c0, r0, PI, TAU), reverse(ell(c1, r1, PI, TAU))]))
# a cone standing on the circle (c, r) with its apex hs above c on screen
let lean = |r, hs| arcsin(r * ST / hs)
let Cone = |c, r, hs, col, amount = 0.35, w = 2.5| fill{tint(col, amount)} stroke{col, w}
    Polygon(flatten([[c + [0, hs, 0]], ell(c, r, PI - lean(r, hs), TAU + lean(r, hs))]))