Chapter 19
Herds
The farms along the road are crowds of billboards: herds of cows on the left, herds of pigs on the right. A herd is a list of placed billboards. The CowHerd and PigHerd modules lay the animals out again for each frame that needs them.
Cows §
The world stores a cow herd as two counts: how many cows, and how many rows stand behind the front one. The route's herd is fourteen cows, in columns of three:
## The herd's cows behind `herd_along`, column by column from the front,
## led by the bull at `herd_along` if the herd has one.
herd_cows : CowHerd, { herd_along : Along, bull : CowHerd.Bull } -> List(Geom.Placed(Billboard))
herd_cows = |CowHerd.({ cow_count, rows_behind_front }), { herd_along, bull }| {
cows =
List.from_iter(U64.until(0, cow_count))
.map(|cow_number| herd_cow({ herd_along, cow_number, rows_behind_front }))
match bull {
WithBull => [herd_bull(herd_along)].concat(cows)
NoBull => cows
}
}
U64.until(0, cow_count) counts the cows, and herd_cow places the cow with each number. A bull, if the herd has one, goes at the front of the list.
A herd in a perfect grid would look like a parking lot, so each cow strays a little from its place:
## The herd's cow at `cow_number`, counting from 0. The scatter's phases, 2.7
## along the road and 1.9 across it, are chosen by eye.
herd_cow : {
herd_along : Along,
cow_number : U64,
rows_behind_front : U64,
} -> Geom.Placed(Billboard)
herd_cow = |{ herd_along, cow_number, rows_behind_front }| {
cows_per_column = rows_behind_front + 1
column = cow_number.div_trunc_by(cows_per_column).to_f64()
row = cow_number.rem_by(cows_per_column).to_f64()
herd_front = herd_along.plus(gap_behind_bull)
column_place = herd_front.plus(column_spacing.times(column))
in_line = column_place.plus(row_stagger.times(row))
row_place = front_row_distance.plus(row_depth.times(row))
stray = Scatter.stray_of(
cow_number,
{
along_phase: 2.7,
across_phase: 1.9,
jitter_along,
jitter_across,
},
)
out_from_road = row_place.plus(stray.across)
{
road_point: {
along: in_line.plus(stray.along),
across: Across.left_of_middle(out_from_road),
},
lift: Distance.zero,
kind: cow_billboard(cow_number),
}
}
The cow's number picks its column and its row: div_trunc_by divides and drops the remainder, and rem_by keeps only the remainder. Each row stands a little further along the road than the one in front of it, and further from the road. Then Scatter.stray_of moves the cow a little, along and across, with two phases, 2.7 and 1.9, chosen by eye. stray_of derives the stray from the cow's number, so it looks random and comes out the same on every run. The last expression is the placed cow: a place on the road, a lift of zero, and the billboard cow_billboard picks, a calf for every fourth cow.
Pigs §
A pig herd has two shapes, as a tag union:
## The herd's pigs about `herd_along`.
herd_pigs : PigHerd, Along -> List(Geom.Placed(Billboard))
herd_pigs = |herd, herd_along|
match herd {
BigHerd(big_herd) => big_herd_pigs(big_herd, herd_along)
TwoRows => two_row_pigs(herd_along)
}
The first two herds of pigs are big, seven rows of seven, and the rest are two short rows. A BigHerd carries its sizes, and TwoRows is a plain tag, so each branch of the match calls the function for its shape. In the first two herds, one pig stands out from the rest and catches the rider's eye, and the rider's chapters in the second half come back to it.
BillboardSighting sights every herd's billboards, as the pipeline sights any thing beside the road.
The herds are the last of the animals that stand still. Everything in the frame at step 1,529 now has its chapter, except the things that move: the cat, the bird and the truck. The first half of the book ends here: one frame, built part by part, from the things beside the road to the world they stand in.