feat(kicad9): snap 2-pin parts onto IC pins, post-route visual optimization#302
feat(kicad9): snap 2-pin parts onto IC pins, post-route visual optimization#302lachlanfysh wants to merge 7 commits into
Conversation
Post-route visual optimization that moves resistors, caps, and LEDs onto their connected IC pins for cleaner schematics. Includes T-junction staggering for repeated patterns, power cap offset wires, power bus wire generation, no-connect flags, and label suppression for wired pins. All snap features are guarded behind snap_ran detection so they only activate when _snap_two_pin_parts actually modified the node, preserving identical behavior for circuits that don't use auto_stub or don't have snap-eligible parts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Snap geometry functions (snap_two_pin_parts, stagger, pre-shift) are backend-agnostic — they operate on Point/Tx/orientation strings, not KiCad S-expressions. Moved to schematics/ per maintainer feedback. KiCad-specific sexp output (wireable nets, power bus wires, no-connect flags) stays in tools/kicad9/sexp_schematic.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Re: architecture feedback from #297 — on review the snap geometry was already backend-agnostic (operates on Point/Tx/orientation strings, no S-expression references), so I've moved it to The split is now:
|
|
Thanks for making the changes and rebasing onto the |
|
I'm going to close this PR. Eventually we'll merge code from your |
The snap-v2 refactor lost two features from the original snap-placement branch: 1. Connectivity-aware fallback: when routing fails, try placement with real connectivity at increasing expansion factors before falling back to full label-only output. Calls snap_two_pin_parts() to wire close 2-pin parts directly. 2. Label deconfliction: post-pass that detects global_label overlap with component bounding boxes and nudges labels along their direction axis. MR-1 test: switch sheet wires 0→36 (was 63 on v1 branch — remaining gap is power symbol rendering, not yet ported to v2). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sing Two fixes to match v1 branch output quality: 1. Power symbol rotation: rotate GND/supply symbols based on calc_pin_dir() so they point away from the connected component, matching KiCad convention. Previously all power symbols were at angle=0 regardless of pin direction. 2. Remove snap_ran guard: _find_wireable_nets, _gen_power_bus_wires, and _gen_no_connect_flags now run unconditionally instead of only when snap marker attributes are present. This matches v1 behavior where these always ran. Also removes snap_ran from the force-emit condition for power labels on 2-pin parts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l wires When a hierarchical subcircuit's routing fails (e.g. daisy_seed with 27 parts), the RoutingFailure propagated to the root and triggered the full-circuit fallback — stubbing ALL nets across ALL subcircuits and destroying wires in successfully-routed sheets like switch_input and led_drivers. Now each child's routing failure is caught independently: the failed child's nets are stubbed and re-routed with labels, while all other children keep their wired connections. This is the correct behavior — one complex subcircuit should degrade gracefully, not poison the whole schematic. MR-1 result: switch_input wires 36→45, routing succeeds on normal path instead of falling through to fallback. Only daisy_seed (the actual failure) gets labels-only output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
High-fanout nets are now marked _deferred_stub instead of immediately stubbed, preserving connectivity for placement grouping. After placement, _apply_deferred_stubs() classifies each net per-subcircuit: short-distance nets with few pins stay as wires, others get stubbed. A rescue pass un-stubs auto-stubbed nets that ended up close together. Also adds SIGALRM-based routing timeouts (child + top-level), progressive stubbing fallback when routing fails, and KeyError handling for switchbox creation edge cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverting the removal of net.stub checks in get_internal_nets() and get_internal_pins(). Without these checks, fully-stubbed nets (power, classified-as-too-far) leak into the routing graph, causing the router to attempt wires instead of clean labels — producing broken connections and displaced labels. Deferred-stub nets don't need this removal since _stub stays False during placement; only _deferred_stub is set. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Note: I'm currently debugging regressions in the v2 branch ( |
|
Update: regressions resolved on Root cause identified: the
Fix approach on
Output now exactly matches #297 quality across all 14 hierarchical sheets (verified wire/label counts per sheet). 63 tests pass. Branch: |
|
Which of my branches should I merge |
|
`lachlanfysh-pr/kicad9-snap-v2` would be cleanest — v3 is based on `development` (same ancestor as v2) so it should merge without conflicts, and it supersedes everything on v2. v3 is 2 commits on `development`:
Both are self-contained against `development`, so merging into `development` directly would also work if you'd prefer to skip the intermediate branch. |
|
I've merged your |
Summary
Post-route visual optimization for KiCad 9 schematic generation that snaps 2-pin parts (resistors, caps, LEDs) onto their connected IC pins, producing cleaner schematics with fewer floating labels.
Rebased onto
developmentbranch per review feedback on #297. Adopts the upstream hierarchical UUID path threading and 4-tuple return pattern fromnode_to_sexp_schematic.Features (gen_schematic.py)
Features (sexp_schematic.py)
no_connectmarkersSafety
snap_randetection — only activates when_snap_two_pin_partsactually modified the nodedevelopmentTest plan
test_and_gate_erc_cleanpasses (0-2 fixable ERC errors)🤖 Generated with Claude Code