# 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

(

2

inch

,

2

inch

)

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.5

w

,

0.5

h

)),

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

),

0

w

,

0

h

)),

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.5

mm

,

0.5

mm

]),

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>"""

)