# This notebook is a semi top-down explanation. This cell needs to be # executed first so that the operators and helper functions are defined # All of this is explained in the later half of the notebook using Compose, Interact Compose.set_default_graphic_size(2inch, 2inch) points_f = [ (.1, .1), (.9, .1), (.9, .2), (.2, .2), (.2, .4), (.6, .4), (.6, .5), (.2, .5), (.2, .9), (.1, .9), (.1, .1) ] f = compose(context(), stroke("black"), line(points_f)) rot(pic) = compose(context(rotation=Rotation(-deg2rad(90))), pic) flip(pic) = compose(context(mirror=Mirror(deg2rad(90), 0.5w, 0.5h)), pic) above(m, n, p, q) = compose(context(), (context(0, 0, 1, m/(m+n)), p), (context(0, m/(m+n), 1, n/(m+n)), q)) above(p, q) = above(1, 1, p, q) beside(m, n, p, q) = compose(context(), (context(0, 0, m/(m+n), 1), p), (context(m/(m+n), 0, n/(m+n), 1), q)) beside(p, q) = beside(1, 1, p, q) over(p, q) = compose(context(), (context(), p), (context(), q)) rot45(pic) = compose(context(0, 0, 1/sqrt(2), 1/sqrt(2), rotation=Rotation(-deg2rad(45), 0w, 0h)), pic) # Utility function to zoom out and look at the context zoomout(pic) = compose(context(), (context(0.2, 0.2, 0.6, 0.6), pic), (context(0.2, 0.2, 0.6, 0.6), fill(nothing), stroke("black"), strokedash([0.5mm, 0.5mm]), polygon([(0, 0), (1, 0), (1, 1), (0, 1)]))) function read_path(p_str) tokens = [try parsefloat(x) catch symbol(x) end for x in split(p_str, r"[\s,]+")] path(tokens) end fish = compose(context(units=UnitBox(260, 260)), stroke("black"), read_path(strip(readall("fish.path")))) rotatable(pic) = @manipulate for θ=0:0.001:2π compose(context(rotation=Rotation(θ)), pic) end blank = compose(context()) fliprot45(pic) = rot45(compose(context(mirror=Mirror(deg2rad(-45))),pic)) # Hide this cell. display(MIME("text/html"), """<script> var cell = \$(".container .cell").eq(0), ia = cell.find(".input_area") if (cell.find(".toggle-button").length == 0) { ia.after( \$('<button class="toggle-button">Toggle hidden code</button>').click( function (){ ia.toggle() } ) ) ia.hide() } </script>""")