1{
2
3// Animate a shape by twisting along the Z axis.
4// f maps time onto the twist rate,
5// which is the angle of twist (counterclockwise)
6// per unit increase along the Z axis.
7a_twist f shape =
8    let b = shape.bbox;
9        r = max(map mag [
10                [b.[MIN,X], b.[MIN,Y]],
11                [b.[MAX,X], b.[MIN,Y]],
12                [b.[MIN,X], b.[MAX,Y]],
13                [b.[MAX,X], b.[MAX,Y]],
14            ]);
15    in make_shape {
16        dist [x,y,z,t] =
17            let xy = cmul[[x,y], cis(z * -f t)];
18            in shape.dist[xy.[X], xy.[Y], z, t],
19        colour [x,y,z,t] =
20            let xy = cmul[[x,y], cis(z * -f t)];
21            in shape.colour[xy.[X], xy.[Y], z, t],
22        bbox = [[-r,-r,b.[MIN,Z]], [r,r,b.[MAX,Z]]],
23        is_3d = true,
24    };
25
26// Animate a shape by moving it around.
27//  f maps time onto a translation offset [x,y,z].
28//  bbox is the minimum and maximum offset values.
29a_move {f,bbox} shape =
30    make_shape {
31        dist [x,y,z,t] :
32            let offset = f t;
33            in shape.dist [x-offset.[X],y-offset.[Y],z-offset.[Z],t],
34        colour [x,y,z,t] :
35            let offset = f t;
36            in shape.colour [x-offset.[X],y-offset.[Y],z-offset.[Z],t],
37        bbox : shape.bbox + bbox,
38        is_2d : shape.is_2d,
39        is_3d : shape.is_3d,
40    };
41
42}
43