Geometry (olympiad)
Every construction is live — the derived points recompute as the inputs move.
Each block is the whole file — copy it into x.manic and run manic x.manic (live) or --record out (video).
geo-pythagoras-short
A vertical Short proving a² + b² = c² by area — and a demo that a shader art panel and
generic geometry share ONE frame at full value. The top third is a living domain-warped
aurora plasma (pure per-pixel art, black below a crisp seam); the bottom hosts a 3-4-5 right
triangle that is DRAWN OUT edge by edge — untraced(id) starts each polygon at 0% so
draw(id, dur) pens its outline on while the fill washes in — then squares bloom on the
legs (9, 16) and the hypotenuse (25) until 9 + 16 = 25 → a² + b² = c². Split-stage compo,
creator branding, RaTeX equations.
// geo-pythagoras-short — a SPLIT STAGE: the top third of the frame is a living
// generative `shader` artwork (domain-warped aurora plasma — pure art, showing off what
// per-pixel shaders do), and the bottom two-thirds is the most famous theorem in
// geometry drawn out on black: a 3-4-5 right triangle whose squares bloom to 9 + 16 = 25
// → a² + b² = c². Two concepts, one frame — the shader and the maths each at full value.
//
// manic examples/geo-pythagoras-short.manic
title("Why a² + b² = c²");
canvas("9:16");
template("black");
creator(me, "@anish2good name=Manic tagline=Turn_plain_text_into_math_videos yt=zarigatongy x=@anish2good web=8gwifi.org/manic accent=cyan secondary=magenta footer=signature cta=Try_it_free safe=reels");
// ===================== TOP STAGE : the shader as ART =====================
// A bold domain-warped flow field confined to the top band (v < BAND); pure black
// below it, with a crisp accent rule marking the seam. This is the shader showcase —
// motion, depth and colour, all one closed-form expression per pixel.
shader(art) {
let band = 0.34;
let inside = 1.0 - smoothstep(band - 0.02, band, v); // 1 in the top band, 0 below
// domain warp: fold the plane through itself twice for turbulent, liquid flow
let x = (u - 0.5) * asp;
let y = v / band; // 0 at top → 1 at the seam
let w1 = sin(x * 3.0 + t * 0.5) + cos(y * 4.0 - t * 0.3);
let w2 = sin((x + w1) * 2.6 - t * 0.4) * cos((y + w1) * 3.2 + t * 0.25);
let flow = 0.5 + 0.5 * sin(x * 4.0 + w2 * 2.2 + t * 0.6);
let bands = 0.5 + 0.5 * sin(y * 9.0 - w2 * 3.0 + t * 0.5); // aurora curtains
let hue = mod(244 + flow * 118 + w2 * 44, 360); // magenta → cyan aurora
let sat = 0.82;
let base = (0.14 + 0.62 * flow * bands) * inside;
// crisp bright accent rule along the seam (the two stages meet here)
let rule = smoothstep(0.006, 0.0, abs(v - band));
let val = base + rule * 0.85;
}
// ===================== BOTTOM STAGE : the proof on black =====================
// geometry of the 3-4-5 right triangle, sized + placed to live entirely below the seam
let ux = w * 0.070; // one unit
let ox = w * 0.36; // right-angle vertex x
let oy = h * 0.75; // right-angle vertex y (well below the art band)
// vertices: C (right angle), A (end of the 4-leg), B (end of the 3-leg)
point(pC, (ox, oy));
point(pA, (ox + 4*ux, oy));
point(pB, (ox, oy - 3*ux));
hidden(pC); hidden(pA); hidden(pB);
polygon(tri, (ox, oy), (ox + 4*ux, oy), (ox, oy - 3*ux), cyan);
rightangle(ra, pA, pC, pB);
// `untraced` starts a shape drawn-to-0% (opacity stays 1) so `draw` can pen it on —
// the outline traces edge by edge while the fill washes in.
untraced(tri); hidden(ra);
// squares on the two legs (areas 16 and 9) and on the hypotenuse (area 25)
polygon(sqA, (ox, oy), (ox + 4*ux, oy), (ox + 4*ux, oy + 4*ux), (ox, oy + 4*ux), gold);
polygon(sqB, (ox, oy), (ox, oy - 3*ux), (ox - 3*ux, oy - 3*ux), (ox - 3*ux, oy), lime);
polygon(sqC, (ox + 4*ux, oy), (ox + 7*ux, oy - 4*ux), (ox + 3*ux, oy - 7*ux), (ox, oy - 3*ux), magenta);
untraced(sqA); untraced(sqB); untraced(sqC);
// side length labels — on the triangle's own edges (dark ink on the cyan face)
caption(lb, "3", (ox + 26, oy - 1.5*ux), 32); color(lb, #06202a);
caption(la, "4", (ox + 2*ux, oy - 28), 32); color(la, #06202a);
caption(lc, "5", (ox + 2.6*ux, oy - 1.9*ux), 32); color(lc, #06202a);
hidden(la); hidden(lb); hidden(lc);
// area labels, sitting in each square (dark ink on the bright leg-squares, white on the hyp)
caption(cA, "16", (ox + 2*ux, oy + 2*ux), 44); color(cA, #101018);
caption(cB, "9", (ox - 1.5*ux, oy - 1.5*ux), 44); color(cB, #101018);
caption(cC, "25", (ox + 3.5*ux, oy - 3.5*ux), 44); color(cC, white);
hidden(cA); hidden(cB); hidden(cC);
// the payoff equations — tucked under the diagram, along the bottom edge
equation(eqn, (w*0.5, h*0.955), `9 + 16 = 25`, 46); hidden(eqn);
equation(eq2, (w*0.5, h*0.955), `a^2 + b^2 = c^2`, 46); hidden(eq2);
// hook + point text — in the seam gap between the art band and the diagram
caption(hook, "Why is this ALWAYS a right triangle?", (w*0.5, h*0.42), 32);
caption(point, "Every right triangle. Always.", (w*0.5, h*0.42), 34);
hidden(hook); hidden(point);
// ================= script =================
show(hook);
wait(2.4);
fade(hook, 0.4);
// BUILD — the triangle is DRAWN OUT edge by edge, then the right angle + side labels
draw(tri, 1.4);
wait(0.4);
show(ra);
wait(0.4);
show(la); show(lb); show(lc);
wait(1.2);
// RULE — squares DRAW out on the legs (pen tracing each side), then the areas appear
draw(sqA, 1.1); draw(sqB, 1.1);
wait(0.5);
show(cA); show(cB);
wait(1.4);
// then the hypotenuse square draws out — the payoff shape
draw(sqC, 1.3);
wait(0.5);
show(cC);
wait(1.6);
// TWIST — the two small squares add up to the big one
pulse(sqA, 1.4); pulse(sqB, 1.4);
show(eqn);
wait(1.6);
pulse(sqC, 1.6);
fade(eqn, 0.4);
show(eq2);
wait(2.0);
// POINT + hold
show(point);
wait(2.6);
endcard(me, "title=Try_Manic cta=8gwifi.org/manic");
circle-in-three
A Problem Book plate (paper + masthead): split one round cake among three friends with exactly
TWO straight cuts. Wrong guesses first, then the lemma (crossing cuts always give four pieces), then
the transcendental equation cos⁻¹(u) − u√(1−u²) = π/3 solved on a live graph, then the fair cut —
with the three piece percentages recomputing throughout. The solved height u = a/R = 0.2649.
// circle-in-three — a story-driven textbook plate: divide one round cake among
// three friends using exactly two straight cuts. Wrong ideas first, then the
// lemma (crossing cuts always give four pieces), then the transcendental
// equation, solved on a graph, then the fair cut - live percentages throughout.
// The solved height: cos^-1(u) - u sqrt(1-u^2) = pi/3 => u = a/R = 0.2649.
title("Split a Circle in Three - with Two Lines");
canvas("16:9");
template("paper");
masthead("The Problem Book", "Plate VII");
// ---------- layout ----------
let R = 205;
let ox = 400;
let oy = 400;
let dyE = R/3; // "evenly spaced" cut height (the wrong guess)
let dyS = 0.2649*R; // the solved cut height
let sf = 1.0228; // chord length ratio: sqrt(1-0.2649^2)/sqrt(8/9)
// ---------- HUD ----------
text(head, (cx, 100), "Split a Circle in Three - with Two Lines"); display(head); cursor(head); sticky(head);
text(cap, (cx, h - 40), ""); size(cap, 26); sticky(cap);
text(fig, (ox, 648), ""); size(fig, 24); color(fig, dim); sticky(fig);
// ---------- the cake ----------
circle(cake, (ox, oy), R); outlined(cake); stroke(cake, 3); untraced(cake);
// attempt 1: two diameters
line(d1, (ox, oy - R), (ox, oy + R)); untraced(d1); stroke(d1, 3);
line(d2, (ox - R, oy), (ox + R, oy)); untraced(d2); stroke(d2, 3);
text(q1, (ox + 70, oy - 70), "1"); size(q1, 30); hidden(q1); tag(q1, qlab);
text(q2, (ox - 70, oy - 70), "2"); size(q2, 30); hidden(q2); tag(q2, qlab);
text(q3, (ox - 70, oy + 70), "3"); size(q3, 30); hidden(q3); tag(q3, qlab);
text(q4, (ox + 70, oy + 70), "4"); size(q4, 30); hidden(q4); tag(q4, qlab);
// attempt 2: parallel cuts at thirds (they will SLIDE to the true height later)
line(cA1, (ox - R*0.94281, oy - dyE), (ox + R*0.94281, oy - dyE)); untraced(cA1); stroke(cA1, 4); color(cA1, red);
line(cB1, (ox - R*0.94281, oy + dyE), (ox + R*0.94281, oy + dyE)); untraced(cB1); stroke(cB1, 4); color(cB1, red);
// boolean sources (hidden): the disc and the horizontal bands
circle(disc, (ox, oy), R); hidden(disc);
rect(rT2, (ox, oy - dyE - 75), 430, 150); hidden(rT2);
rect(rM2, (ox, oy), 430, 2*dyE); hidden(rM2);
rect(rB2, (ox, oy + dyE + 75), 430, 150); hidden(rB2);
rect(rT3, (ox, oy - dyS - 75), 430, 150); hidden(rT3);
rect(rM3, (ox, oy), 430, 2*dyS); hidden(rM3);
rect(rB3, (ox, oy + dyS + 75), 430, 150); hidden(rB3);
// the three shares, evenly-spaced version (29.2 / 41.7 / 29.2)
intersect(capT2, disc, rT2); color(capT2, cyan); opacity(capT2, 0.45); hidden(capT2); tag(capT2, att2);
intersect(mid2, disc, rM2); color(mid2, gold); opacity(mid2, 0.45); hidden(mid2); tag(mid2, att2);
intersect(capB2, disc, rB2); color(capB2, magenta); opacity(capB2, 0.45); hidden(capB2); tag(capB2, att2);
// the three shares, solved version (33.3 each)
intersect(capT3, disc, rT3); color(capT3, cyan); opacity(capT3, 0.45); hidden(capT3); tag(capT3, att3);
intersect(mid3, disc, rM3); color(mid3, gold); opacity(mid3, 0.45); hidden(mid3); tag(mid3, att3);
intersect(capB3, disc, rB3); color(capB3, magenta); opacity(capB3, 0.45); hidden(capB3); tag(capB3, att3);
// live percentages, one per share
counter(pcT, (ox, oy - 128), 0, 1, "", "%"); hidden(pcT);
counter(pcM, (ox, oy), 0, 1, "", "%"); hidden(pcM);
counter(pcB, (ox, oy + 128), 0, 1, "", "%"); hidden(pcB);
// ---------- the mathematics panel (right side) ----------
equation(eqA, (960, 205), `A_{\text{cap}}(a) \;=\; R^2\cos^{-1}\!\frac{a}{R} \;-\; a\sqrt{R^2-a^2}`, 32); hidden(eqA); sticky(eqA);
equation(eqG, (960, 430), `f(u)=\cos^{-1}u \;-\; u\sqrt{1-u^2} \;-\; \tfrac{\pi}{3}`, 26); hidden(eqG); sticky(eqG);
arrow(gxa, (850, 560), (1195, 560)); untraced(gxa); stroke(gxa, 2);
arrow(gya, (880, 655), (880, 495)); untraced(gya); stroke(gya, 2);
plot(pf, (880, 560), 300, 90, "acos(x)-x*sqrt(1-x^2)-1.047198", (0.01, 0.99));
untraced(pf); stroke(pf, 3); color(pf, blue);
roots(rt, pf, magenta); hidden(rt);
text(rlab, (1040, 596), "u ≈ 0.2649"); size(rlab, 24); color(rlab, magenta); hidden(rlab);
// ================= timeline =================
// ---- the problem
type(head, 1.1);
say(cap, "Three friends. One round cake. Two straight cuts. Make it fair.", 0.6);
draw(cake, 1.2);
say(fig, "Fig. 1 - the cake", 0.3);
wait(0.5);
// ---- attempt 1: through the middle, twice
cue(whoosh);
say(cap, "First idea: cut through the middle - twice.", 0.5);
par { draw(d1, 0.7); draw(d2, 0.7); }
stagger(0.12) { show(q1, 0.3); show(q2, 0.3); show(q3, 0.3); show(q4, 0.3); }
say(cap, "Four pieces. Perfectly equal - and perfectly useless. We are THREE.", 0.5);
wait(0.6);
// ---- the lemma: crossing cuts always make four
say(cap, "Tilt a cut, slide it anywhere: two CROSSING cuts always make four pieces.", 0.5);
rotate(d2, 38, 1.0, smooth);
shift(d2, (55, 35), 1.0, smooth);
pulse(qlab, 0.8);
say(cap, "Lemma: the two cuts must never cross inside the cake. They must be PARALLEL.", 0.5);
cue(tick);
par { fade(d1, 0.5); fade(d2, 0.5); fade(qlab, 0.4); }
// ---- attempt 2: parallel, evenly spaced
say(fig, "Fig. 2 - parallel cuts at thirds", 0.3);
say(cap, "Second idea: space the parallel cuts evenly - at thirds of the diameter.", 0.5);
par { draw(cA1, 0.7); draw(cB1, 0.7); }
stagger(0.15) { show(capT2, 0.5); show(mid2, 0.5); show(capB2, 0.5); }
par { show(pcT, 0.3); show(pcM, 0.3); show(pcB, 0.3); }
par { to(pcT, value, 29.2, 1.3, smooth); to(pcM, value, 41.7, 1.3, smooth); to(pcB, value, 29.2, 1.3, smooth); }
cue(pop);
flash(mid2, gold);
say(cap, "The middle friend grins: 41.7 percent. Evenly SPACED is not evenly SHARED.", 0.5);
wait(0.8);
// ---- the mathematics: ask the cake
say(cap, "So ask the cake: how much lies beyond a cut at height a?", 0.5);
show(eqA, 0.6);
wait(0.8);
cue(tick);
rewrite(eqA, `R^2\cos^{-1}\!\frac{a}{R} - a\sqrt{R^2-a^2} \;=\; \frac{\pi R^2}{3}`, 0.9);
say(cap, "Each outer piece must hold a third of the cake. Divide out the radius...", 0.5);
cue(tick);
rewrite(eqA, `\cos^{-1}u \;-\; u\sqrt{1-u^2} \;=\; \frac{\pi}{3}, \qquad u=\frac{a}{R}`, 0.9);
say(cap, "No algebra unties this knot - it is transcendental. Let the graph solve it.", 0.5);
say(fig, "Fig. 3 - solving f(u) = 0", 0.3);
par { draw(gxa, 0.5); draw(gya, 0.5); }
par { draw(pf, 1.3); show(eqG, 0.7); }
show(rt, 0.4); show(rlab, 0.4);
par { cam((959, 545), 1.0, smooth); zoom(1.6, 1.0, smooth); }
flash(rt, magenta);
say(cap, "One root. The cuts belong at u = 0.2649 - about a quarter of the radius.", 0.5);
wait(0.7);
par { cam((cx, cy), 1.0, smooth); zoom(1, 1.0, smooth); }
cue(tick);
rewrite(eqA, `u \;=\; \frac{a}{R} \;\approx\; 0.2649`, 0.9);
// ---- the fair cut: slide the knives home
say(cap, "Nudge each cut toward the centre: from 0.333 R in to 0.2649 R.", 0.5);
cue(whoosh);
par {
shift(cA1, (0, dyE - dyS), 1.4, smooth); scale(cA1, sf, 1.4, smooth);
shift(cB1, (0, dyS - dyE), 1.4, smooth); scale(cB1, sf, 1.4, smooth);
fade(att2, 1.2); show(capT3, 1.2); show(mid3, 1.2); show(capB3, 1.2);
}
par { to(pcT, value, 33.3, 1.3, smooth); to(pcM, value, 33.3, 1.3, smooth); to(pcB, value, 33.3, 1.3, smooth); }
cue(chime);
par { flash(capT3, cyan); flash(mid3, gold); flash(capB3, magenta); }
say(cap, "33.3 - 33.3 - 33.3. Fair, to the crumb.", 0.5);
say(fig, "Fig. 4 - the fair cut: a = 0.2649 R", 0.3);
wait(0.8);
// ---- closing plate
cue(tick);
rewrite(eqA, `\boxed{\;a \;=\; 0.2649\,R\;}`, 1.0);
par {
breathe(eqA, 3, 0.05, 0, 5);
seq { pulse(capT3, 0.7); pulse(mid3, 0.7); pulse(capB3, 0.7); }
}
say(cap, "Two cuts. Three equal shares. One transcendental number.", 0.6);
wait(2.5);
circle-thirds-no-triangle
Problem Book Plate VIII: cut a circle into three EQUAL areas — but the classic three-sector answer (and the equilateral triangle hiding inside it) is banned. Two triangle-free solutions: the bullseye (concentric circles at r₁ = R/√3, r₂ = R√(2/3)) and the waves (S-curves of semicircular arcs on a thirds-divided diameter), each piece proven to equal πR²/3 exactly. A 1,000-entity constructed proof.
// circle-thirds-no-triangle — Plate VIII of the Problem Book: cut a circle
// into three EQUAL areas, but the classic three-sector answer (and the
// equilateral triangle hiding inside it) is banned. Two triangle-free answers:
// 1. the bullseye: concentric circles at r1 = R/sqrt(3), r2 = R sqrt(2/3)
// 2. the waves: S-curves of semicircular arcs on a thirds-divided diameter;
// piece_k = (pi/2)(r_k^2 - r_{k-1}^2) + (pi/2)(s_{k-1}^2 - s_k^2)
// = (pi R^2/18)[(2k-1) + (7-2k)] = pi R^2 / 3 for EVERY k.
title("Three Equal Parts - No Triangles Allowed");
canvas("16:9");
template("paper");
masthead("The Problem Book", "Plate VIII");
// ---------- layout ----------
let R = 205;
let ox = 400;
let oy = 400;
let r1 = R*0.57735; // R / sqrt 3
let r2 = R*0.8165; // R sqrt(2/3)
// ---------- HUD ----------
text(head, (cx, 100), "Three Equal Parts - No Triangles Allowed"); display(head); cursor(head); sticky(head);
text(cap, (cx, h - 40), ""); size(cap, 26); sticky(cap);
text(fig, (ox, 648), ""); size(fig, 24); color(fig, dim); sticky(fig);
// ---------- the cake ----------
circle(cake, (ox, oy), R); outlined(cake); stroke(cake, 3); untraced(cake);
circle(disc, (ox, oy), R); hidden(disc); // hidden filled source for booleans
// ---------- act 1: the banned answer ----------
line(m1, (ox, oy), (ox, oy - R)); untraced(m1); stroke(m1, 3); tag(m1, merc);
line(m2, (ox, oy), (ox - R*0.866, oy + R*0.5)); untraced(m2); stroke(m2, 3); tag(m2, merc);
line(m3, (ox, oy), (ox + R*0.866, oy + R*0.5)); untraced(m3); stroke(m3, 3); tag(m3, merc);
line(e1, (ox, oy - R), (ox - R*0.866, oy + R*0.5)); dashed(e1); stroke(e1, 3); color(e1, red); untraced(e1); tag(e1, tri);
line(e2, (ox - R*0.866, oy + R*0.5), (ox + R*0.866, oy + R*0.5)); dashed(e2); stroke(e2, 3); color(e2, red); untraced(e2); tag(e2, tri);
line(e3, (ox + R*0.866, oy + R*0.5), (ox, oy - R)); dashed(e3); stroke(e3, 3); color(e3, red); untraced(e3); tag(e3, tri);
// ---------- act 2: the bullseye ----------
circle(c1, (ox, oy), r1); outlined(c1); stroke(c1, 3); untraced(c1); tag(c1, bull);
circle(c2, (ox, oy), r2); outlined(c2); stroke(c2, 3); untraced(c2); tag(c2, bull);
circle(c1d, (ox, oy), r1); hidden(c1d);
circle(c2d, (ox, oy), r2); hidden(c2d);
circle(fin, (ox, oy), r1); color(fin, cyan); opacity(fin, 0.45); hidden(fin); tag(fin, bull);
difference(ringM, c2d, c1d); color(ringM, gold); opacity(ringM, 0.45); hidden(ringM); tag(ringM, bull);
difference(ringO, disc, c2d); color(ringO, magenta); opacity(ringO, 0.45); hidden(ringO); tag(ringO, bull);
counter(pb1, (ox, oy), 0, 1, "", "%"); hidden(pb1); tag(pb1, bull);
counter(pb2, (ox, oy - 143), 0, 1, "", "%"); hidden(pb2); tag(pb2, bull);
counter(pb3, (ox, oy + 186), 0, 1, "", "%"); hidden(pb3); tag(pb3, bull);
equation(eqB, (960, 210), `\pi r_1^2 \;=\; \pi\big(r_2^2-r_1^2\big) \;=\; \pi\big(R^2-r_2^2\big) \;=\; \frac{\pi R^2}{3}`, 26); hidden(eqB); sticky(eqB);
// ---------- act 3: the waves ----------
// construction guides: the diameter, divided into thirds
line(diam, (ox - R, oy), (ox + R, oy)); dashed(diam); stroke(diam, 2); color(diam, dim); untraced(diam); tag(diam, guide);
dot(dv1, (ox - R/3, oy), 6); color(dv1, gold); hidden(dv1); tag(dv1, guide);
dot(dv2, (ox + R/3, oy), 6); color(dv2, gold); hidden(dv2); tag(dv2, guide);
// cut 1: semicircle r = R/3 above on the first third + r = 2R/3 below on the rest
plot(pU1, (ox, oy), R, R, "sqrt(abs(0.111111-(x+0.666667)^2))", (-1, -0.3333));
untraced(pU1); stroke(pU1, 4); color(pU1, red); tag(pU1, waves);
plot(pL1, (ox, oy), R, R, "0-sqrt(abs(0.444444-(x-0.333333)^2))", (-0.3333, 1));
untraced(pL1); stroke(pL1, 4); color(pL1, red); tag(pL1, waves);
// cut 2: semicircle r = 2R/3 above on the first two thirds + r = R/3 below
plot(pU2, (ox, oy), R, R, "sqrt(abs(0.444444-(x+0.333333)^2))", (-1, 0.3333));
untraced(pU2); stroke(pU2, 4); color(pU2, red); tag(pU2, waves);
plot(pL2, (ox, oy), R, R, "0-sqrt(abs(0.111111-(x-0.666667)^2))", (0.3333, 1));
untraced(pL2); stroke(pL2, 4); color(pL2, red); tag(pL2, waves);
// boolean sources: half-disc sectors + the four construction circles.
// key fact: consecutive half-discs are INTERNALLY TANGENT, so every wave piece is
// either a plain sector or ONE difference(sector, circle) - no nesting needed.
sector(sLoB, (ox, oy), R, 180, 360); hidden(sLoB);
sector(sHiB, (ox, oy), R, 0, 180); hidden(sHiB);
sector(sU2s, (ox - R/3, oy), 2*R/3, 0, 180); hidden(sU2s);
sector(sL1s, (ox + R/3, oy), 2*R/3, 180, 360); hidden(sL1s);
circle(dU1c, (ox - 2*R/3, oy), R/3); hidden(dU1c);
circle(dU2c, (ox - R/3, oy), 2*R/3); hidden(dU2c);
circle(dL1c, (ox + R/3, oy), 2*R/3); hidden(dL1c);
circle(dL2c, (ox + 2*R/3, oy), R/3); hidden(dL2c);
// region 1 (cyan): lower-left crescent + its little bump above the diameter
difference(w1a, sLoB, dL1c); color(w1a, cyan); opacity(w1a, 0.45); filled(w1a); tag(w1a, wave1); tag(w1a, waves);
sector(sU1f, (ox - 2*R/3, oy), R/3, 0, 180); color(sU1f, cyan); opacity(sU1f, 0.45); filled(sU1f); tag(sU1f, wave1); tag(sU1f, waves);
// region 2 (gold): the S in the middle - one piece above the axis, one below
difference(w2a, sU2s, dU1c); color(w2a, gold); opacity(w2a, 0.45); filled(w2a); tag(w2a, wave2); tag(w2a, waves);
difference(w2b, sL1s, dL2c); color(w2b, gold); opacity(w2b, 0.45); filled(w2b); tag(w2b, wave2); tag(w2b, waves);
// region 3 (magenta): upper-right crescent + its little bump below
difference(w3a, sHiB, dU2c); color(w3a, magenta); opacity(w3a, 0.45); filled(w3a); tag(w3a, wave3); tag(w3a, waves);
sector(sL2f, (ox + 2*R/3, oy), R/3, 180, 360); color(sL2f, magenta); opacity(sL2f, 0.45); filled(sL2f); tag(sL2f, wave3); tag(sL2f, waves);
hidden(wave1); hidden(wave2); hidden(wave3);
counter(pc1, (300, 492), 0, 1, "", "%"); hidden(pc1);
counter(pc2, (370, 360), 0, 1, "", "%"); hidden(pc2);
counter(pc3, (508, 308), 0, 1, "", "%"); hidden(pc3);
equation(eqW, (960, 210), `\text{piece}_k=\frac{\pi}{2}\big(r_k^2-r_{k-1}^2\big)+\frac{\pi}{2}\big(s_{k-1}^2-s_k^2\big)`, 26); hidden(eqW); sticky(eqW); z(eqW, 10);
// ================= timeline =================
// ---- the challenge
type(head, 1.1);
say(cap, "Cut a circle into three equal parts. Everyone knows the answer...", 0.6);
draw(cake, 1.2);
say(fig, "Fig. 1 - the answer everyone knows", 0.3);
par { draw(m1, 0.5); draw(m2, 0.5); draw(m3, 0.5); }
say(cap, "Three cuts from the centre, 120 degrees apart. Equal - by symmetry.", 0.5);
wait(0.5);
say(cap, "But look what hides inside it...", 0.5);
par { draw(e1, 0.5); draw(e2, 0.5); draw(e3, 0.5); }
flash(tri, red);
cue(pop);
say(cap, "An equilateral triangle. And today, triangles are BANNED.", 0.5);
wait(0.5);
par { disintegrate(e1, 0.7); disintegrate(e2, 0.7); disintegrate(e3, 0.7); disintegrate(m1, 0.7); disintegrate(m2, 0.7); disintegrate(m3, 0.7); }
// ---- answer one: the bullseye
cue(whoosh);
say(fig, "Fig. 2 - the bullseye", 0.3);
say(cap, "Answer one: forget cuts across - aim for the BULLSEYE.", 0.5);
par { draw(c1, 0.8); draw(c2, 0.8); }
stagger(0.15) { show(fin, 0.5); show(ringM, 0.5); show(ringO, 0.5); }
par { show(pb1, 0.3); show(pb2, 0.3); show(pb3, 0.3); }
par { to(pb1, value, 33.3, 1.2, smooth); to(pb2, value, 33.3, 1.2, smooth); to(pb3, value, 33.3, 1.2, smooth); }
show(eqB, 0.6);
cue(tick);
rewrite(eqB, `r_1=\frac{R}{\sqrt{3}}\approx 0.577\,R \qquad r_2=R\sqrt{\tfrac{2}{3}}\approx 0.816\,R`, 0.9);
say(cap, "A disc and two rings, each exactly a third. No corners anywhere.", 0.5);
wait(1.2);
par { fade(bull, 0.6); disintegrate(eqB, 0.8); }
// ---- answer two: the waves
cue(whoosh);
say(fig, "Fig. 3 - the waves", 0.3);
say(cap, "Answer two: let the cuts WAVE. Divide the diameter into thirds...", 0.5);
draw(diam, 0.7);
par { show(dv1, 0.4); show(dv2, 0.4); }
say(cap, "...then each cut is two half-circles: one arching over, one diving under.", 0.5);
par { cam((ox, oy), 1.0, smooth); zoom(1.25, 1.0, smooth); }
seq { draw(pU1, 0.9); draw(pL1, 0.9); }
cue(tick);
seq { draw(pU2, 0.9); draw(pL2, 0.9); }
stagger(0.15) { show(wave1, 0.6); show(wave2, 0.6); show(wave3, 0.6); }
par { show(pc1, 0.3); show(pc2, 0.3); show(pc3, 0.3); }
par { to(pc1, value, 33.3, 1.2, smooth); to(pc2, value, 33.3, 1.2, smooth); to(pc3, value, 33.3, 1.2, smooth); }
par { cam((cx, cy), 1.0, smooth); zoom(1, 1.0, smooth); }
// the telescoping proof
show(eqW, 0.6);
say(cap, "Why equal? Each piece is half-circles added and subtracted...", 0.5);
cue(tick);
rewrite(eqW, `\text{piece}_k=\frac{\pi R^2}{18}\Big[(2k-1)+(7-2k)\Big]`, 0.9);
say(cap, "...and the k cancels itself. Every wave weighs the same.", 0.5);
cue(tick);
rewrite(eqW, `\boxed{\;\text{piece}_k=\frac{\pi R^2}{3}\quad\text{for every }k\;}`, 1.0);
cue(chime);
par { flash(wave1, cyan); flash(wave2, gold); flash(wave3, magenta); }
wait(0.8);
// ---- finale: still fair, whichever way it turns
say(fig, "Fig. 4 - still fair, spinning", 0.3);
par { fade(pc1, 0.4); fade(pc2, 0.4); fade(pc3, 0.4); fade(guide, 0.4); }
say(cap, "And a third stays a third, whichever way you turn the plate.", 0.5);
par {
turn(waves, (ox, oy), 120, 5.0, smooth);
breathe(eqW, 3, 0.05, 0, 5);
}
say(cap, "Three equal parts - and not a triangle in sight.", 0.6);
wait(2.0);
equilateral
Euclid I.1 — an equilateral triangle from two circles.
// Equilateral Triangle — Euclid, Elements Book I, Proposition 1. Given a segment
// AB: draw the circle centred at A through B and the circle centred at B through
// A; where they cross is the apex of an equilateral triangle. Every side then
// equals AB. It's a fully DYNAMIC construction — drag B at the end and the
// circles, the intersection, and the triangle all stay correct.
//
// New geo builtins: circle2 (circle by centre + a point on it) and circlecircle
// (the two intersection points of two circles).
//
// Note: each compass circle has radius |AB|, so keep A and B close enough that
// the circles fit the canvas (here |AB| ~ 200 px).
//
// manic examples/equilateral.manic
title("Equilateral Triangle");
canvas("16:9");
text(head, (cx, 96), "Euclid I.1 -- two circles give an equilateral triangle");
color(head, cyan); size(head, 24); hidden(head);
point(A, (540, 470), "A");
point(B, (740, 470), "B");
segment(ab, A, B); color(ab, fg); stroke(ab, 3); untraced(ab);
// the two compass circles (each of radius AB)
circle2(cA, A, B); color(cA, dim); stroke(cA, 1.5); untraced(cA);
circle2(cB, B, A); color(cB, dim); stroke(cB, 1.5); untraced(cB);
// where they meet: C0 (below AB) and C1 (above AB) — take the apex above
circlecircle(C, A, B, B, A);
hidden(C0); hidden(C1);
label(C1, "C", (16, -16)); color(C1.label, lime);
segment(ac, A, C1); color(ac, lime); stroke(ac, 3); untraced(ac);
segment(bc, B, C1); color(bc, lime); stroke(bc, 3); untraced(bc);
// --- construct it ---
show(head, 0.5);
show(A, 0.3); show(B, 0.3);
draw(ab, 0.6);
section("Two circles");
par { draw(cA, 0.9); draw(cB, 0.9); }
show(C1, 0.4);
section("The triangle");
par { draw(ac, 0.7); draw(bc, 0.7); }
par { pulse(ac); pulse(bc); pulse(ab); }
wait(0.6);
// --- drag a vertex: it stays equilateral (circles stay on-canvas) ---
section("Drag a vertex");
move(B, (700, 360), 1.6, smooth);
wait(0.3);
move(B, (660, 560), 1.6, smooth);
wait(0.3);
move(B, (740, 470), 1.2, smooth);
wait(1.0);
triangle
A triangle with its centres and cevians.
// Triangle Geometry — the geo kit (olympiad helpers à la olympiad.asy/cse5.asy).
// Points drive everything: circumcircle, incircle, centroid, circumcenter,
// angle mark, and the foot of an altitude are all *constructed* from A, B, C.
//
// manic examples/triangle.manic
// manic examples/triangle.manic --record out --fps 60
title("Triangle Geometry");
canvas(1280, 720);
text(head, (640, 118), "constructed from three points");
display(head); color(head, cyan); size(head, 32); hidden(head);
text(cap, (640, 668), ""); color(cap, dim); size(cap, 22);
// the three free points
point(A, (380, 560), "A");
point(B, (900, 560), "B");
point(C, (640, 190), "C");
hidden(A); hidden(B); hidden(C);
// sides
segment(ab, A, B); segment(bc, B, C); segment(ca, C, A);
untraced(ab); untraced(bc); untraced(ca);
// constructions
circumcircle(cc, A, B, C); untraced(cc);
circumcenter(O, A, B, C); hidden(O);
incircle(ic, A, B, C); untraced(ic);
centroid(G, A, B, C); hidden(G);
anglemark(angC, A, C, B); untraced(angC);
foot(F, C, A, B); hidden(F);
segment(alt, C, F); untraced(alt);
// --- script ---
show(head, 0.5);
say(cap, "three points make a triangle");
par { show(A); show(B); show(C); }
par { draw(ab, 0.5); draw(bc, 0.5); draw(ca, 0.5); }
draw(angC, 0.4);
wait(0.5);
section("Circumcircle");
say(cap, "the unique circle through all three vertices");
par { show(O); draw(cc, 0.9); }
wait(0.6);
section("Incircle & Centroid");
say(cap, "incircle (tangent to all sides) and centroid");
par { draw(ic, 0.9); show(G); }
wait(0.6);
section("Altitude");
say(cap, "drop a perpendicular from C to AB — its foot F");
par { show(F); draw(alt, 0.6); }
flash(F, magenta);
wait(1.0);
// the payoff: constructions are dynamic — drag a vertex and everything
// (circumcircle, incircle, centroid, foot, angle mark, sides) recomputes.
section("Drag a vertex");
say(cap, "move C — every construction follows");
move(C, (430, 230), 1.2, smooth);
move(C, (850, 210), 1.2, smooth);
move(C, (640, 190), 1.0, smooth);
say(cap, "and drag A");
move(A, (300, 520), 0.9, smooth);
move(A, (380, 560), 0.8, smooth);
wait(1.2);
incircle_tangents
The incircle and its tangent points.
// The Incircle & Contact Triangle — the incircle touches each side at the foot
// of the perpendicular from the incenter, and each radius meets the side at a
// right angle. The three touch points form the contact triangle.
//
// manic examples/incircle_tangents.manic
// manic examples/incircle_tangents.manic --record out --fps 60
title("The Incircle");
canvas(1280, 720);
text(head, (640, 120), "tangent to all three sides");
display(head); color(head, cyan); size(head, 28); hidden(head);
text(cap, (640, 668), ""); color(cap, dim); size(cap, 22);
point(A, (300, 560), "A");
point(B, (1000, 560), "B");
point(C, (640, 160), "C");
hidden(A); hidden(B); hidden(C);
segment(ab, A, B); segment(bc, B, C); segment(ca, C, A);
untraced(ab); untraced(bc); untraced(ca);
incenter(I, A, B, C); color(I, cyan); label(I, "I", (16, -14)); hidden(I);
incircle(ic, A, B, C); untraced(ic);
// touch points = feet of perpendiculars from I to each side
foot(tBC, I, B, C); foot(tCA, I, C, A); foot(tAB, I, A, B);
color(tBC, magenta); color(tCA, magenta); color(tAB, magenta);
hidden(tBC); hidden(tCA); hidden(tAB);
// radii to the touch points, with right-angle marks
segment(rBC, I, tBC); segment(rCA, I, tCA); segment(rAB, I, tAB);
color(rBC, lime); color(rCA, lime); color(rAB, lime);
untraced(rBC); untraced(rCA); untraced(rAB);
rightangle(qBC, I, tBC, B); rightangle(qCA, I, tCA, C); rightangle(qAB, I, tAB, A);
untraced(qBC); untraced(qCA); untraced(qAB);
// the contact triangle
segment(k1, tBC, tCA); segment(k2, tCA, tAB); segment(k3, tAB, tBC);
untraced(k1); untraced(k2); untraced(k3);
show(head, 0.5);
say(cap, "a triangle and its incentre I");
par { show(A); show(B); show(C); }
par { draw(ab, 0.5); draw(bc, 0.5); draw(ca, 0.5); }
show(I, 0.3);
wait(0.3);
section("Inscribed circle");
say(cap, "the incircle touches each side once");
draw(ic, 1.0);
stagger(0.15) { show(tBC); show(tCA); show(tAB); }
wait(0.3);
section("Radii ⟂ sides");
say(cap, "each radius meets its side at a right angle");
par { draw(rBC, 0.5); draw(rCA, 0.5); draw(rAB, 0.5); }
par { draw(qBC, 0.4); draw(qCA, 0.4); draw(qAB, 0.4); }
wait(0.4);
section("Contact triangle");
say(cap, "the three touch points form the contact triangle");
par { draw(k1, 0.5); draw(k2, 0.5); draw(k3, 0.5); }
wait(1.2);
tangents
Tangent lines from a point to a circle.
// Tangent Lines — the two tangents from an external point P to a circle, and
// the theorem that each tangent is perpendicular to the radius at its touch
// point. Everything is a DYNAMIC construction: move P and the touch points,
// tangent lines, radii, and right-angle marks all recompute live.
//
// New geo builtins: circle2 (circle by centre + a point on it), tangent
// (touch points from an external point), plus segment/rightangle tracking them.
//
// manic examples/tangents.manic
title("Tangent Lines");
canvas("16:9");
text(head, (cx, 96), "two tangents from a point -- each meets the radius at 90 degrees");
color(head, cyan); size(head, 24); hidden(head);
point(O, (520, 400), "O");
point(A, (520, 200)); // a point on the circle -> radius 200
point(P, (940, 380), "P");
hidden(A); // A just defines the radius; don't show it
circle2(circ, O, A); color(circ, dim); stroke(circ, 2); untraced(circ);
// the two touch points t0 / t1, and the tangent lines to them
tangent(t, P, O, A);
segment(l0, P, t0); color(l0, cyan); stroke(l0, 3); untraced(l0);
segment(l1, P, t1); color(l1, cyan); stroke(l1, 3); untraced(l1);
// radius to each touch point + the right-angle marks
segment(r0, O, t0); color(r0, dim); untraced(r0);
segment(r1, O, t1); color(r1, dim); untraced(r1);
rightangle(ra0, O, t0, P); color(ra0, lime); hidden(ra0);
rightangle(ra1, O, t1, P); color(ra1, lime); hidden(ra1);
// --- reveal ---
show(head, 0.5);
draw(circ, 0.8);
show(O, 0.3); show(P, 0.3);
section("The tangents");
par { draw(l0, 0.7); draw(l1, 0.7); }
show(t0, 0.3); show(t1, 0.3);
section("Radius meets tangent");
par { draw(r0, 0.5); draw(r1, 0.5); }
par { show(ra0, 0.4); show(ra1, 0.4); }
wait(0.6);
// --- prove it's dynamic: move P, everything tracks ---
section("Move the point");
move(P, (820, 230), 1.6, smooth);
wait(0.4);
move(P, (980, 470), 1.6, smooth);
wait(0.8);
move(P, (940, 380), 1.2, smooth);
wait(1.0);
orthocenter
The orthocentre from the three altitudes.
// Altitudes & Orthocenter — the three altitudes of a triangle meet at one
// point, the orthocenter H. Each altitude drops perpendicular to a side.
// Dynamic: drag a vertex and the altitudes still concur.
//
// manic examples/orthocenter.manic
// manic examples/orthocenter.manic --record out --fps 60
title("Altitudes & Orthocenter");
canvas(1280, 720);
text(head, (640, 120), "the three altitudes concur");
display(head); color(head, cyan); size(head, 28); hidden(head);
text(cap, (640, 668), ""); color(cap, dim); size(cap, 22);
point(A, (330, 540), "A");
point(B, (980, 560), "B");
point(C, (700, 190), "C");
hidden(A); hidden(B); hidden(C);
segment(ab, A, B); segment(bc, B, C); segment(ca, C, A);
untraced(ab); untraced(bc); untraced(ca);
// feet of the three altitudes
foot(fA, A, B, C); foot(fB, B, C, A); foot(fC, C, A, B);
color(fA, magenta); color(fB, magenta); color(fC, magenta);
hidden(fA); hidden(fB); hidden(fC);
// the altitudes themselves
segment(hA, A, fA); segment(hB, B, fB); segment(hC, C, fC);
color(hA, lime); color(hB, lime); color(hC, lime);
untraced(hA); untraced(hB); untraced(hC);
rightangle(qA, A, fA, B); rightangle(qB, B, fB, C); rightangle(qC, C, fC, A);
untraced(qA); untraced(qB); untraced(qC);
orthocenter(H, A, B, C); color(H, cyan); label(H, "H", (16, -14)); hidden(H);
show(head, 0.5);
say(cap, "a triangle");
par { show(A); show(B); show(C); }
par { draw(ab, 0.5); draw(bc, 0.5); draw(ca, 0.5); }
wait(0.3);
section("Drop the altitudes");
say(cap, "from each vertex, perpendicular to the opposite side");
seq {
par { draw(hA, 0.5); draw(qA, 0.4); show(fA); }
par { draw(hB, 0.5); draw(qB, 0.4); show(fB); }
par { draw(hC, 0.5); draw(qC, 0.4); show(fC); }
}
wait(0.3);
section("Orthocenter");
say(cap, "all three meet at the orthocenter H");
show(H, 0.4);
flash(H, magenta);
wait(0.6);
section("Drag a vertex");
say(cap, "move C — the altitudes still concur");
move(C, (520, 230), 1.2, smooth);
move(C, (820, 250), 1.2, smooth);
move(C, (700, 190), 1.0, smooth);
wait(1.0);
euler_line
The Euler line through centroid, circumcentre, orthocentre.
// The Euler Line — in any triangle, the circumcenter O, centroid G, and
// orthocenter H are collinear (and OG : GH = 1 : 2). Constructions are
// dynamic: drag C and the three centres stay on one line.
//
// manic examples/euler_line.manic
// manic examples/euler_line.manic --record out --fps 60
title("The Euler Line");
canvas(1280, 720);
text(head, (640, 120), "circumcenter, centroid, orthocenter — collinear");
display(head); color(head, cyan); size(head, 26); hidden(head);
text(cap, (640, 668), ""); color(cap, dim); size(cap, 22);
point(A, (300, 560), "A");
point(B, (1000, 540), "B");
point(C, (560, 190), "C");
hidden(A); hidden(B); hidden(C);
segment(ab, A, B); segment(bc, B, C); segment(ca, C, A);
untraced(ab); untraced(bc); untraced(ca);
circumcircle(cc, A, B, C); untraced(cc);
circumcenter(O, A, B, C); color(O, magenta); label(O, "O", (18, -14)); hidden(O);
centroid(G, A, B, C); color(G, lime); label(G, "G", (18, -14)); hidden(G);
orthocenter(H, A, B, C); color(H, cyan); label(H, "H", (-30, -14)); hidden(H);
segment(euler, O, H); color(euler, magenta); stroke(euler, 3); untraced(euler);
show(head, 0.5);
say(cap, "any triangle, with its circumcircle");
par { show(A); show(B); show(C); }
par { draw(ab, 0.5); draw(bc, 0.5); draw(ca, 0.5); }
draw(cc, 0.9);
wait(0.4);
section("Three centres");
say(cap, "circumcenter O, centroid G, orthocenter H");
stagger(0.3) { show(O); show(G); show(H); }
wait(0.4);
section("The Euler line");
say(cap, "they always lie on a single line");
draw(euler, 0.9);
wait(0.6);
section("Drag a vertex");
say(cap, "move C — O, G, H stay collinear");
move(C, (770, 220), 1.2, smooth);
move(C, (420, 250), 1.2, smooth);
move(C, (560, 190), 1.0, smooth);
wait(1.0);
nine_point
The nine-point circle.
// The Nine-Point Circle — one circle through the three side-midpoints AND the
// three altitude feet. (It's the circumcircle of the medial triangle.)
// Dynamic: drag C and the circle still catches all six points.
//
// manic examples/nine_point.manic
// manic examples/nine_point.manic --record out --fps 60
title("The Nine-Point Circle");
canvas(1280, 720);
text(head, (640, 120), "three midpoints + three feet, one circle");
display(head); color(head, cyan); size(head, 26); hidden(head);
text(cap, (640, 668), ""); color(cap, dim); size(cap, 22);
point(A, (320, 560), "A");
point(B, (1000, 560), "B");
point(C, (620, 175), "C");
hidden(A); hidden(B); hidden(C);
segment(ab, A, B); segment(bc, B, C); segment(ca, C, A);
untraced(ab); untraced(bc); untraced(ca);
// side midpoints
midpoint(mAB, A, B); midpoint(mBC, B, C); midpoint(mCA, C, A);
color(mAB, lime); color(mBC, lime); color(mCA, lime);
hidden(mAB); hidden(mBC); hidden(mCA);
// altitude feet
foot(fA, A, B, C); foot(fB, B, C, A); foot(fC, C, A, B);
color(fA, magenta); color(fB, magenta); color(fC, magenta);
hidden(fA); hidden(fB); hidden(fC);
// the nine-point circle = circumcircle of the medial triangle
circumcircle(npc, mAB, mBC, mCA); outline(npc, cyan); untraced(npc);
show(head, 0.5);
say(cap, "start with a triangle");
par { show(A); show(B); show(C); }
par { draw(ab, 0.5); draw(bc, 0.5); draw(ca, 0.5); }
wait(0.3);
section("Six points");
say(cap, "the three side-midpoints (lime)");
stagger(0.2) { show(mAB); show(mBC); show(mCA); }
say(cap, "and the three altitude feet (magenta)");
stagger(0.2) { show(fA); show(fB); show(fC); }
wait(0.4);
section("One circle");
say(cap, "a single circle passes through all six");
draw(npc, 1.0);
wait(0.6);
section("Drag a vertex");
say(cap, "move C — the circle still catches all six");
move(C, (820, 220), 1.3, smooth);
move(C, (440, 240), 1.3, smooth);
move(C, (620, 175), 1.0, smooth);
wait(1.0);
conics
Ellipse, parabola, hyperbola.
// The Conic Sections — the three curves you get by slicing a cone: the ellipse,
// the parabola, and the hyperbola. Each is a geo-kit primitive; they reveal one
// at a time with the defining property.
//
// manic examples/conics.manic
// manic examples/conics.manic --template blueprint
title("The Conic Sections");
canvas("16:9");
text(head, (cx, 80), "three curves from slicing a cone");
display(head); color(head, cyan); size(head, 26); hidden(head);
text(cap, (cx, 662), ""); color(cap, dim); size(cap, 23);
// --- ellipse (left) ---
ellipse(el, (300, 400), 165, 100); color(el, cyan); stroke(el, 3); untraced(el);
text(ell, (300, 250), "ellipse"); color(ell, cyan); size(ell, 26); hidden(ell);
// --- parabola (centre) ---
parabola(pa, (660, 540), 150, 270); color(pa, lime); stroke(pa, 3); untraced(pa);
text(pal, (660, 235), "parabola"); color(pal, lime); size(pal, 26); hidden(pal);
// --- hyperbola (right) — two branches, tagged `hy` ---
hyperbola(hy, (1010, 400), 55, 120); color(hy, magenta); stroke(hy, 3); untraced(hy);
text(hyl, (1010, 205), "hyperbola"); color(hyl, magenta); size(hyl, 26); hidden(hyl);
// --- reveal ---
show(head, 0.5);
section("Ellipse");
say(cap, "ellipse -- the sum of distances to two foci stays constant");
draw(el, 0.9);
show(ell, 0.4);
wait(0.5);
section("Parabola");
say(cap, "parabola -- every point is equidistant from a focus and a line");
draw(pa, 0.9);
show(pal, 0.4);
wait(0.5);
section("Hyperbola");
say(cap, "hyperbola -- two branches; the difference of distances stays constant");
draw(hy, 0.9);
show(hyl, 0.4);
wait(1.4);