MODULE BinPack; CONST TotalW = 400, TotalH = 150, Jump = 100; VAR width, ht, loc, color; (* "width" is the width of each bin (and hence, weight). "ht" is the height of the current weight, "loc" is the location of the current weight's northwest corner, and "color" is the color of the current weight. *) VAR hue, hueDelta; (* "hue" is the hue of the current color; "hueDelta" is the change in the hue to use from weight to weight. *) PROC Setup(nBins, nWeights) IS width := TotalW / (nBins + 2); hue := 0; hueDelta := 1 / (nWeights + 1); DrawBar(); Anim.ClearPerm(); Anim.AddPerm(DrawBar) END; PROC DrawBar() IS SAVE PS IN PS.MoveTo((0, TotalH)); PS.LineTo((TotalW, TotalH)); PS.SetWidth(3); PS.Stroke() END END; PROC NewWeight(id, wt) IS ht := wt * TotalH; loc := (0, ht); color := Color.FromHSV(hue, 1, 1); hue := hue + hueDelta; DrawWt(loc, ht, color) END; PROC DrawWt(p, h, c) IS Rect.Draw(p, R2.Plus(p, (width, -h))); SAVE PS IN PS.SetColor(c); PS.Fill() END; PS.SetWidth(3); PS.Stroke() END; (* Draw a weight with its northwest corner at "p", with height "h", and fill color "c". *) PROC Pack(bin, total) IS VAR endLoc, cl IN endLoc := (width * (2 + bin), total * TotalH); cl := CLOSE(DrawWtT, loc, endLoc); Anim.Play((cl, 1)); loc := endLoc END END; FUNC p = Interp(a, b, t) IS p = (t, 0) REL (a, b) END; FUNC p = BezierPt(a, b, c, d, t) IS (E ab, bc, cd, abc, bcd :: ab = Interp(a, b, t) AND bc = Interp(b, c, t) AND cd = Interp(c, d, t) AND abc = Interp(ab, bc, t) AND bcd = Interp(bc, cd, t) AND p = Interp(abc, bcd, t)) END; FUNC p = Above(q) IS p = R2.Plus(q, (0, Jump)) END; PROC DrawWtT(loc, endLoc, t) IS VAR p IN p := BezierPt(loc, Above(loc), Above(endLoc), endLoc, t); DrawWt(p, ht, color) END END; PROC Place() IS Anim.AddPerm(CLOSE(DrawWt, loc, ht, color)) END; PROC SmallRun() IS Setup(2, 3); NewWeight(0, 0.7); Pack(0, 0.7); Place(); NewWeight(1, 0.6); Pack(0, 1.3); Pack(1, 0.6); Place(); NewWeight(2, 0.35); Pack(0, 1.05); Pack(1, 0.95); Place() END; UI PointTool(SmallRun); PROC BigRun() IS Setup(6, 9); NewWeight(0, 0.7); Pack(0, 0.7); Place(); NewWeight(1, 0.6); Pack(0, 1.3); Pack(1, 0.6); Place(); NewWeight(2, 0.35); Pack(0, 1.05); Pack(1, 0.95); Place(); NewWeight(3, 0.4); Pack(0, 1.1); Pack(1, 1.35); Pack(2, 0.4); Place(); NewWeight(4, 0.7); Pack(0, 1.4); Pack(1, 1.65); Pack(2, 1.1); Pack(3, 0.7); Place(); NewWeight(5, 0.2); Pack(0, 0.9); Place(); NewWeight(6, 0.4); Pack(0, 1.3); Pack(1, 1.35); Pack(2, 0.8); Place(); NewWeight(7, 0.9); Pack(0, 1.8); Pack(1, 1.85); Pack(2, 1.7); Pack(3, 1.6); Pack(4, 0.9); Place(); NewWeight(8, 0.25); Pack(0, 1.15); Pack(1, 1.2); Pack(2, 1.05); Pack(3, 0.95); Place() END; UI PointTool(BigRun);