IMPORT PS, R2, Type, Unparse, Color, Show, Text, Anim; PRIVATE CONST A = (0, -100), B = (100, -100), C = (100, -220), DeltaT = 0.4 / 5, CurvePower = 4; VAR low := -1.2, high := 1.2, frameNum := 0, labelPt := R2.PlusY(P(low), 10); PRIVATE PROC ShowFrameNum() IS Type.R(C, Unparse.Value(frameNum)); frameNum := frameNum + 1 END; PRIVATE FUNC p = P(t) IS (E t2 = t * t :: p = (t, t2 * t2) REL (A, B)) END; PRIVATE FUNC dp = DP(t) IS (E t2 = t * t :: dp = 4 * t2 * t) END; PRIVATE PRED Perp(u, v) IS CAR(u) * CAR(v) + CDR(u) * CDR(v) = 0 END; PRIVATE FUNC q = Q(t) IS (E p = P(t) :: q ~ (0, 1) REL (A, B) AND (p, q) CONG (A, B) AND Perp(R2.Minus(q, p), (1, DP(t)))) END; PRIVATE PROC DrawCurve() IS SAVE PS IN VAR t = low IN PS.MoveTo(P(t)); t := t + 0.1; DO t < high -> PS.LineTo(P(t)); t := t + 0.1 OD; PS.LineTo(P(high)) END; PS.SetWidth(3); PS.Stroke() END END; PROC DrawBar(t) IS SAVE PS IN VAR p, q IN p := P(t); q := Q(t); PS.MoveTo(q); PS.LineTo((-1, 0) REL (p, q)); PS.SetWidth(3); PS.Stroke() END END END; PROC DrawTrajectory(start, stop) IS SAVE PS IN VAR t = start IN PS.MoveTo(Q(t)); t := t + 0.05; DO t < stop -> PS.LineTo(Q(t)); t := t + 0.05 OD; PS.LineTo(Q(stop)) END; PS.SetColor(Color.Red); PS.Stroke() END END; PRIVATE PROC TypeFunc(p) IS SAVE PS IN PS.SetFontFace("Times-Italic"); Type.R(p, "y ="); PS.MoveTo(p); Show.L(" x"); PS.SetFont("Times-Roman", PS.GetFontSize() - 1); PS.Type(R2.Plus(PS.CurrentPoint(), (2, PS.GetFontPtSize() / 3)), Text.FromNum(CurvePower, 1)) END END; PROC Bg() IS PS.SetFont("Times-Roman", PS.Huge); PS.SetColor(Color.Black); TypeFunc(labelPt); DrawCurve() END; PRIVATE VAR oldT := 0; PROC Frame(t) IS IF t = low -> Bg(); PS.SavePage() | { SKIP | PS.RestorePage() }; DrawTrajectory(MAX(low, oldT - 0.05), t); PS.SavePage() FI; DrawBar(t); oldT := t END; CONST InitDelay = 0.1; PROC t := WarpT(t0) IS IF t0 < InitDelay -> t := low | t0 := (t0 - InitDelay) / (1 - InitDelay); t := low + (high - low) * t0 FI END; PROC an := New() IS an := (Frame, 1); an := Anim.WarpTime(an, WarpT); an := Anim.Scale(an, 8) END; PROC Start() IS Bg(); DrawBar(low) END; UI PointTool(Start); PROC Go() IS PS.Reset(); Anim.Play(New()) END; UI PointTool(Go); PROC Cmd0() IS Start() END; PROC Cmd1() IS SKIP END;