Pads snapped to a grid, then traces routed one at a time until every pad is on the same net.
Pads, on a grid, without collisions
float gridStep = PadSize * Alignment * 2f;
rx = MathF.Round(rx / gridStep) * gridStep;
ry = MathF.Round(ry / gridStep) * gridStep;
Candidate positions are drawn uniformly and then snapped to a coarse grid. That one
rounding is what makes the result look like a circuit board rather than like a scatter:
real boards align their pads, and alignment is the difference between engineering and
confetti.
Snapped candidates are then rejected if they fall outside a circular boundary, or too
close to an existing pad, and the loop gives up after ten times as many attempts as
there are pads to place.
The pads alone. Every one of them is in its final position; nothing after this moves
them.
Routing, nearest first
The traces are built as a spanning tree, one edge at a time:
var lonePads = Enumerable.Range(0, pads.Count).ToList();
var usedPads = new List<int>();
The first trace joins the closest pair anywhere on the board. Every trace after that
finds the shortest connection between the network built so far and a pad not yet on it,
and adds that.
That is Prim’s algorithm, and the result is a minimum spanning tree: the shortest total
wiring that connects everything, with exactly n − 1 traces for n pads and no loop
anywhere. A loop would be a short circuit.
A quarter of the traces.
Half. Traces are drawn as outlines rather than as strokes: the Outliner takes a
centre line and a thickness and emits the two edges of the resulting shape. So a trace
is a long thin loop, and where it meets a pad the two outlines merge.
That is what a plotter needs — a pen cannot lay down a two-millimetre track, it can
only draw its edges — and it is why the piece reads as a technical drawing of a board
rather than as a board.
Three quarters. A trace routed later cuts the outline of one routed earlier, because
the outliner clips against everything already added. The order of routing is therefore
visible in the drawing, in which outline survives at a crossing.
Every pad connected: ninety-nine traces for a hundred pads.
Six boards
| Rendering | Pads | Pad size | Alignment | Clearance | Thickness | Stroke | Ink |
|---|
| Amber PCB Grid | 100 | 3.0 | 1.4 | — | 2 | 0.25 | amber on near-black |
| Copper PCB Heavy | 80 | 3.5 | 1.7 | — | 3 | 0.25 | copper on near-black |
| Teal PCB Dense | 150 | 2.5 | 1.2 | — | 2 | 0.25 | teal on near-black |
| Gold PCB Sparse | 60 | 4.0 | 2.0 | — | 2 | 0.25 | gold on near-black |
| Ivory PCB Fine | 140 | 2.3 | 1.15 | — | 2 | 0.20 | ivory on black |
| Slate PCB Open | 55 | 4.2 | 2.2 | 0.3 | 2 | 0.25 | slate blue on near-black |
Alignment is the multiplier on the snapping grid: raise it and the pads sit on a
coarser lattice, which makes the traces more orthogonal and the board tidier; lower it
towards zero and the snapping stops mattering.
Determinism
The generator is the project’s seeded RNG, seeded from the preset and consumed in two
phases — pad placement first, then one draw to pick the starting pad for the routing.
Everything else is exact geometry.