A shape of your own

The collection ships 39 shapes, and the one you have in mind is probably not among them. It does not have to be: plotOptions.unit.positions is a function from the marks and the plot rectangle to places, and everything in the kit is one of those. Three routes in, depending on what you have.

None of the shapes on this page are built in. Each is defined in this sample's own head script, in the lines shown under it.

Route 1 · you have an outline

3,460 adoptions, in a paw

shapeFrom(path) takes SVG path data and returns a shape. The packer does the rest: rows across the outline, each row cut into the spans that fall inside it, and the gap between dots bisected until the spans hold exactly the number of marks the data asks for. Five subpaths here, all wound the same way, so the pad and the toes union into one shape.

1 dot = 5 adoptions

Route 2 · your thing is a line

15,000 trail visits, along the ridge

A ridge, a route or a signal has no interior, and drawing both sides of one by hand means mitring every corner. strokeFrom(path, { width }) takes the centreline instead and thickens it, so the outline is six points long. A stroke also degrades kindly: run it short of dots and it becomes a dotted line, which still reads as the same line.

1 dot = 24 visits · bands ordered along the walk

Route 3 · you have a rule, not a picture

1,000 wristbands, on a spiral

No outline, and no import from the kit at all: a plain function that returns { id, x, y } per mark is already a valid layout. This one is the sunflower spiral. Because the marks arrive in series order and the spiral walks outward, the tiers land as rings, which is worth knowing when you write your own: the order the marks come in is the order your rule sees them.

1 dot = 1 wristband

Authoring an outline