CONST R = 72, N = 10, Base = 2 * R * SIN(Math.Pi / (2 * N)), Height = R / Base; PROC HalfMouth(a, center, dir) IS VAR i IN i := 0; DO i # N / 2 -> VAR b ~ (1, dir) REL (center, a) IN (b, center) CONG (a, center) AND Geometry.Dist(a, b) = Base -> Wedge(a, b, dir); a := b; i := i + 1 END OD END END; PROC Mouth(a, center) IS HalfMouth(a, center, 0.1); HalfMouth(a, center, -0.1) END; UI PointTool(Mouth); VAR CircleColor := Color.Blue; PROC Wedge(a, b, dir) IS VAR c IN c := (0.5, Sgn(dir) * Height) REL (a, b); SAVE PS IN PS.MoveTo(a); PS.LineTo(b); PS.LineTo(c); PS.Close(); SAVE PS IN PS.SetColor(CircleColor); PS.Fill() END; PS.SetColor(Color.White); PS.SetJointStyle(PS.RoundJoints); PS.Stroke() END END END; PROC res := Sgn(d) IS IF d > 0 -> res := 1 | d < 0 -> res := -1 FI END; PROC Open(a, sgn, t) IS VAR theta, tan, dy IN t := t / OpenDur; theta := (1 - t) * (Math.Pi / N) / 2; tan := SIN(theta) / COS(theta); IF tan < 0.001 -> tan := 0.001 | SKIP FI; dy := Base / (2 * tan); Mouth(a, R2.Plus(a, (0, sgn * dy))) END END; CONST Gap = 1.25, RGap = R * Gap, topFrac = 2, botFrac = 2 - topFrac; PROC Sep(a, t) IS t := t / SepDur; VAR gap, top, bot IN gap := (1 - t) * R + t * RGap; top := R2.Plus(a, (0, topFrac * gap)); bot := R2.Plus(a, (0, botFrac * gap)); Mouth(top, R2.Plus(top, (0, -R))); Mouth(bot, R2.Plus(bot, (0, R))) END END; PROC Close(a, t) IS t := t / CloseDur; VAR gap, shift, top, bot IN gap := t * R / 2 + (1 - t) * RGap; shift := t * Base / 4; top := R2.Plus(a, (shift, topFrac * gap)); bot := R2.Plus(a, (-shift, botFrac * gap)); Mouth(top, R2.Plus(top, (0, -100000))); Mouth(bot, R2.Plus(bot, (0, 1e6))) END END; PROC Open2(a, t) IS VAR top, bot IN top := R2.Plus(a, (0, topFrac * RGap)); bot := R2.Plus(a, (0, -botFrac * RGap)); Open(top, -1, t); Open(bot, 1, t) END END; CONST Pi = "p"; PROC TypePi() IS VAR p, w IN p := PS.CurrentPoint(); SAVE PS IN PS.SetFontFace("Symbol"); PS.Type(p, Pi); w := PS.StringWidth(Pi) END; PS.MoveTo(R2.Plus(p, (w, 0))) END END; PROC TypePiR2() IS PS.MoveTo(R2.Plus(PS.CurrentPoint(), (0, -6))); TypePi(); PS.MoveTo(R2.Plus(PS.CurrentPoint(), (2, 0))); VAR p, sz, ptSz, rwidth IN p := PS.CurrentPoint(); sz := PS.GetFontSize(); ptSz := PS.GetFontPtSize(); rwidth := PS.StringWidth("r"); PS.Type(p, "r"); SAVE PS IN PS.SetFontSize(sz - 2); PS.Type(R2.Plus(p, (rwidth + 1, ptSz / 3)), "2") END END END; PROC TypePiR(pt) IS PS.MoveTo(R2.Plus(pt, (0, -6))); TypePi(); PS.MoveTo(R2.Plus(PS.CurrentPoint(), (2, 0))); VAR p, rwidth IN p := PS.CurrentPoint(); rwidth := PS.StringWidth("r"); PS.Type(p, "r") END END; CONST HalfWidth = 10; PROC CType(p) IS PS.MoveTo(R2.Plus(p, (-HalfWidth, 0))); TypePiR2() END; CONST Center = (0, 0), CapSpot = R2.Plus(Center, (0, -40)), UpCenter = R2.Plus(Center, (0, R)); PROC ShowCaption(txt) IS SAVE PS IN PS.SetColor(Color.Black); PS.MoveTo(CapSpot); Show.C(txt) END END; PROC ShowCaptionT(txt, t) IS ShowCaption(txt) END; CONST divCap = "Start with any circle", div2Cap = "Cut it into many small wedges", sepCap = "Divide the wedges into two groups", openCap = "Spread the wedges into combs", closeCap = "Close the combs to make a brick", heightCap = "The brick's height is the radius r", widthCap = "Its width is half the circumference, or ", finCap = "(The animation omitted the parts of\n" & "Archimedes's proof that show that the\n" & "various limits exist.)"; CONST TitleDur1 = 2, TitleDur2 = 2, PauseDur = 1 / 2, DivDur = 2, Div2Dur = 2, SepDur = 2, OpenDur = 2, CloseDur = 2, HeightDur = 3, WidthDur = 3, MulDur = 3, FinDur = 3; CONST PreTime = 1, PostTime = 1; PROC res := MkScene(body, caption, dur) IS res := (CLOSE(SceneT, body, caption, dur), dur + PreTime + PostTime) END; PROC SceneT(body, caption, dur, t) IS IF t < PreTime / 3 -> APPLY(body, 0) | t < PreTime -> APPLY(body, 0); APPLY(caption) | t < PreTime + dur -> APPLY(body, t - PreTime); APPLY(caption) | APPLY(body, dur); APPLY(caption) FI END; PROC res := MkScene2(body, caption, dur) IS res := (CLOSE(SceneT2, body, caption, dur), dur + PreTime + PostTime) END; PROC SceneT2(body, caption, dur, t) IS IF t < PreTime / 2 -> APPLY(caption) | t < (PreTime / 2) + dur -> APPLY(body, t - (PreTime / 2)); APPLY(caption) | APPLY(body, dur); APPLY(caption) FI END; PROC TitleScene1T(t) IS SAVE PS IN PS.SetFontSize(PS.Huge); PS.SetFontFace("Times-Bold"); VAR s, h, cent, pt IN s := "The area of a circle is "; h := PS.StringWidth(s); cent := R2.Minus(Center, (12, 0)); pt := R2.Plus(cent, (h / 2, 0)); PS.SetColor(Color.Black); TypeLinesC.Center(cent, s); PS.MoveTo(R2.Plus(pt, (0, -3))); TypePiR2() END END END; PROC FinSceneT(t) IS TypeLinesC.Center(Center, finCap) END; PROC TitleScene2T(t) IS SAVE PS IN PS.SetFontSize(PS.Huge); PS.SetFontFace("Times-Bold"); IF t < PreTime / 2 -> SKIP | TypeLinesC.Center(Center, "Proof by Archimedes") FI END END; PROC DivSceneT(t) IS SAVE PS IN Circle.Draw(UpCenter, R2.Plus(UpCenter, (R, 0))); PS.SetColor(CircleColor); PS.Fill() END END; PROC Div2SceneT(t) IS Sep(Center, 0) END; PROC PauseT(t) IS SKIP END; PROC HeightT(t) IS Close(Center, CloseDur) END; PROC HeightCap() IS ShowCaption(heightCap); HeightBar(0) END; PROC WidthT(t) IS Close(Center, CloseDur); HeightBar(0) END; PROC MulT(t) IS Close(Center, CloseDur); HeightBar(0); WidthBar(0) END; PROC MulCap() IS MulCapW(R2.Plus(CapSpot, (-(5 / 8) * Unit.In, 0))) END; PROC MulCapW(pt) IS PS.MoveTo(pt); PS.SetFontFace("Times-Roman"); ShowTxt("r"); PS.SetFontFace("Symbol"); ShowTxt(" \264 "); PS.SetFontFace("Times-Roman"); PS.MoveTo(R2.Plus(PS.CurrentPoint(), (0, 6))); TypePiR(PS.CurrentPoint()); PS.MoveTo(R2.Plus(PS.CurrentPoint(), (10, 0))); ShowTxt(" = "); PS.MoveTo(R2.Plus(PS.CurrentPoint(), (0, 6))); TypePiR2() END; PROC ShowTxt(txt) IS VAR w IN w := PS.StringWidth(txt); PS.Type(PS.CurrentPoint(), txt); PS.MoveTo(R2.Plus(PS.CurrentPoint(), (w, 0))) END END; PROC WidthCap() IS VAR s, h, spot, pt IN s := widthCap; h := PS.StringWidth(s); spot := R2.Minus(CapSpot, (8, 0)); pt := R2.Plus(spot, (h / 2, 0)); PS.SetColor(Color.Black); TypeLinesC.Center(spot, s); TypePiR(pt) END; WidthBar(0) END; VAR titleScene1 := (TitleScene1T, TitleDur1), titleScene2 := (TitleScene2T, TitleDur2), divScene := Anim.Co((DivSceneT, DivDur), (CLOSE(ShowCaptionT, divCap), DivDur)), div2Scene := Anim.Co((Div2SceneT, Div2Dur), (CLOSE(ShowCaptionT, div2Cap), Div2Dur)), sepScene := MkScene(CLOSE(Sep, Center), CLOSE(ShowCaption, sepCap), SepDur), openScene := MkScene(CLOSE(Open2, Center), CLOSE(ShowCaption, openCap), OpenDur), closeScene := MkScene(CLOSE(Close, Center), CLOSE(ShowCaption, closeCap), CloseDur), pause := (PauseT, PauseDur), heightScene := MkScene(HeightT, HeightCap, HeightDur), widthScene := MkScene(WidthT, WidthCap, WidthDur), mulScene := MkScene(MulT, MulCap, MulDur), finalScene := (FinSceneT, FinDur); PROC res := All() IS res := titleScene1; res := Anim.Seq(res, titleScene2); res := Anim.Seq(res, pause); res := Anim.Seq(res, divScene); res := Anim.Seq(res, div2Scene); res := Anim.Seq(res, sepScene); res := Anim.Seq(res, openScene); res := Anim.Seq(res, closeScene); res := Anim.Seq(res, heightScene); res := Anim.Seq(res, widthScene); res := Anim.Seq(res, mulScene); res := Anim.Seq(res, finalScene) END; VAR proof := All(); PROC Go() IS Anim.Play(proof) END; UI PointTool(Go); PROC HeightBar(t) IS DrawRBar(R2.Plus(Center, (-Math.Pi * 0.5 * R - 18, R / 2))) END; PROC WidthBar(t) IS DrawPiRBar(R2.Plus(Center, (0, R + 9))) END; PROC DrawRBar(pt) IS TypeLinesC.Center(pt, "r"); Turnstile(R2.Plus(pt, (0, 10)), R2.Plus(pt, (0, R / 2))); Turnstile(R2.Plus(pt, (0, -14)), R2.Plus(pt, (0, -R / 2))) END; PROC DrawPiRBar(pt) IS VAR h IN h := PS.GetFontPtSize() / 4; TypePiR(R2.Plus(pt, (0, 5))); Turnstile(R2.Plus(pt, (-10, h)), R2.Plus(pt, (-Math.Pi * R * 0.5 + (Base / 3), h))); Turnstile(R2.Plus(pt, (28, h)), R2.Plus(pt, (Math.Pi * R * 0.5 + (Base / 3), h))) END END; CONST StileWidth = 10; PROC Turnstile(a, b) IS IF VAR c ~ (1, 0.1) REL (a, b), d ~ (1, -0.1) REL (a, b) IN (c, a) CONG (d, a) AND (c, b) CONG (d, b) AND Geometry.Dist(c, d) = StileWidth -> SAVE PS IN PS.SetColor(Color.Black); PS.SetWidth(1); PS.MoveTo(a); PS.LineTo(b); PS.MoveTo(c); PS.LineTo(d); PS.Stroke() END END FI END; PROC Cmd0() IS IF VAR a ~ (-288.8, -289.5) IN Go() END FI END;