The quadratic solver gives us
continuous optimal positions — floating-point coordinates like (30.0, 50.0). But real PCBs use a
discrete grid (typically 0.1mm or 5-mil steps in imperial units). Components must snap to this grid so traces can align cleanly.
Simple grid snapping rounds each coordinate to the nearest grid point: x_grid = round(x / GRID) × GRID. This works for isolated components but creates
collisions when two components snap to the same cell. In our example, U1 and C1 both solve to (60, 50). After snapping to a 10-unit grid, they'd both land at (60, 50) — a collision!
Collision resolution strategies, from simple to sophisticated:
1.
Shift-to-right: push the second component one grid cell to the right (or down). Simple, fast, used in this example.
2.
Spiral search: expand in a spiral from the target position until an empty cell is found. Minimizes displacement from optimal.
3.
Force-directed refinement: after snapping, run a few iterations of pair-wise repulsion to spread colliding components.
4.
Linear complementarity: formulate legalization as a constrained optimization — minimize displacement while enforcing non-overlap (used in industrial tools like RePlAce).
In our solution, C1 moves from (60, 50) → (70, 50) — shifted right by one grid cell to avoid colliding with U1 at (60, 50). The capacitance-critical connection (weight 1.5) still pulls C1 close to U1 — it's just 10 units away instead of 0. The mathematical equilibrium is preserved as much as possible while respecting physical constraints.
After placement, the next step is
autorouting — connecting all the placed components with copper traces that avoid obstacles and each other.