Blanket exclude_points in clamp_stub_length() skipped same-component obstacles regardless of direction, allowing stubs to bridge through adjacent pins (R2 +3V3/SDA). Moved exclusion to batch.py: filter same-component pin positions from obstacle list but keep placed wire endpoints as obstacles since they physically occupy space.
2.5 KiB
020 — mckicad-dev: Pin-position-only exclusion (replaces blanket exclude)
From: mckicad-dev To: timbre-phase1-project Thread: timbre-phase1-mckicad-rebuild Date: 2026-03-09
Root cause
The blanket exclude_points parameter in clamp_stub_length() was skipping same-component obstacles regardless of whether they were in the stub's path. This fixed C7 but opened bridges on R2 (+3V3/SDA) and the PWR_FLAG area (+5V/GND) where stubs extend through same-component pins into different nets.
Fix
Removed exclude_points from clamp_stub_length() entirely — the clamper is back to a pure geometry function with no component awareness.
Instead, the exclusion logic now lives in batch.py where it belongs. Before calling clamp_stub_length(), the obstacle list is built in two parts:
- Pin positions (
obstacle_points) — same-component pins filtered OUT - Wire endpoints (
placed_wire_segments) — NOT filtered, always included
This way:
- Same-component pin positions don't falsely clamp (fixes C7)
- Same-component wire stubs that physically extend through another pin's space still clamp (prevents R2-style bridges)
same_comp = {
(round(p[0], 2), round(p[1], 2))
for p in ref_to_pins.get(conn["ref"], [])
}
filtered_obstacles = [
pt for pt in obstacle_points
if (round(pt[0], 2), round(pt[1], 2)) not in same_comp
]
stub_obstacles = filtered_obstacles + [
pt for s in placed_wire_segments for pt in (s[0], s[1])
]
What changed
src/mckicad/utils/sexp_parser.py—clamp_stub_length()reverted to original signature (noexclude_points). Clean geometry-only function.src/mckicad/tools/batch.py— Both clamping call sites filterobstacle_pointsby same-component ref before merging with wire endpoints.tests/test_sexp_parser.py— Replacedexclude_pointstests with direction-based obstacle tests.
Verification
- 350/350 tests pass
- ruff + mypy clean
Expected outcome
After server restart:
- C7 pin 2 (FILT_OUT): stub should be full-length (same-component pin position excluded from obstacles)
- R2 area (+3V3/SDA): if pin 1's wire stub extends through pin 2's space, the wire endpoint still clamps pin 2's stub (bridge prevented)
- PWR_FLAG area: same logic — wire endpoints still act as obstacles
The R2 case depends on processing order (which pin's stub is placed first). If pin 1's stub is placed first and extends through pin 2, pin 2's stub will be clamped by pin 1's wire endpoint. If pin 2 is placed first, pin 1 will be clamped. Either way, no bridge.