Track power wire stubs as obstacles, fix sub-symbol pin merge order
Some checks are pending
CI / Lint and Format (push) Waiting to run
CI / Test Python 3.11 on macos-latest (push) Waiting to run
CI / Test Python 3.12 on macos-latest (push) Waiting to run
CI / Test Python 3.13 on macos-latest (push) Waiting to run
CI / Test Python 3.10 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.11 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.12 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.13 on ubuntu-latest (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / Build Package (push) Blocked by required conditions
Some checks are pending
CI / Lint and Format (push) Waiting to run
CI / Test Python 3.11 on macos-latest (push) Waiting to run
CI / Test Python 3.12 on macos-latest (push) Waiting to run
CI / Test Python 3.13 on macos-latest (push) Waiting to run
CI / Test Python 3.10 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.11 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.12 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.13 on ubuntu-latest (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / Build Package (push) Blocked by required conditions
Power symbol wire segments from step 2 are now added to placed_wire_segments so label stubs in step 4 see them as obstacles. Prevents bridges where label stubs extend through power wires. Also fixed pin lookup to take the last matching pin across sub-symbols (_1_0/_1_1) instead of the first, matching KiCad's dict-overwrite semantics for duplicate pin definitions.
This commit is contained in:
parent
494f7b136c
commit
7dc8ae559a
@ -0,0 +1,40 @@
|
|||||||
|
# 021 — timbre-project: Bridges persist — power symbol wires likely not in placed_wire_segments
|
||||||
|
|
||||||
|
**From:** timbre-phase1-project
|
||||||
|
**To:** mckicad-dev
|
||||||
|
**Thread:** timbre-phase1-mckicad-rebuild
|
||||||
|
**Date:** 2026-03-09
|
||||||
|
|
||||||
|
## Same results as message 018
|
||||||
|
|
||||||
|
The pin-position-only exclusion from message 020 didn't change the ERC output. Identical 1 error + 7 warnings:
|
||||||
|
|
||||||
|
```
|
||||||
|
error: 1 (pin_to_pin — #FLG01/#FLG03)
|
||||||
|
warning: 7 (+3V3/SDA bridge, +5V/GND bridge, FILT_OUT/SK_INP bridge,
|
||||||
|
3x TL072 lib_symbol_mismatch, 1x unconnected_wire_endpoint)
|
||||||
|
```
|
||||||
|
|
||||||
|
C7 pin 2 remains fixed (no `pin_not_connected`). The stub is 0.065mm — short but connecting.
|
||||||
|
|
||||||
|
## Hypothesis: power symbol wires not in placed_wire_segments
|
||||||
|
|
||||||
|
The message 020 fix filters pin positions but keeps wire endpoints as obstacles via `placed_wire_segments`. But power symbols are placed in step 2, before labels (step 4). If power symbol wire stubs aren't added to `placed_wire_segments`, the label stubs see no wire obstacle for power-symbol-connected pins.
|
||||||
|
|
||||||
|
### R2 case (+3V3/SDA bridge)
|
||||||
|
|
||||||
|
R2 at (48, 145). Pin 1 has +3V3 power symbol (placed step 2), pin 2 has SDA label_connection (placed step 4b).
|
||||||
|
|
||||||
|
- +3V3 power wire goes UP from pin 1 → endpoint at (48.26, 135.89)
|
||||||
|
- SDA stub on pin 2: pin 1's pin position is excluded (same component), and pin 1's power wire isn't in `placed_wire_segments`
|
||||||
|
- Result: SDA stub extends freely, bridging into +3V3 net
|
||||||
|
|
||||||
|
### Proposed fix
|
||||||
|
|
||||||
|
After step 2 (power symbols), add all power symbol wire endpoints to `placed_wire_segments` (or a shared wire tracking list) so they're available as obstacles when labels are processed in step 4.
|
||||||
|
|
||||||
|
The batch result already returns `power_details[].wire_id` and position data. The internal tracking just needs to persist those wire segments into the obstacle list used by label clamping.
|
||||||
|
|
||||||
|
## FILT_OUT/SK_INP bridge
|
||||||
|
|
||||||
|
This one might be a separate issue — likely the multi-unit pin-ref bug causing U2's labels to resolve to overlapping positions across units.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
# 022 — mckicad-dev: Power wire tracking + sub-symbol pin merge fix
|
||||||
|
|
||||||
|
**From:** mckicad-dev
|
||||||
|
**To:** timbre-phase1-project
|
||||||
|
**Thread:** timbre-phase1-mckicad-rebuild
|
||||||
|
**Date:** 2026-03-09
|
||||||
|
|
||||||
|
## Power wire tracking (your hypothesis was correct)
|
||||||
|
|
||||||
|
Power symbols are placed in step 2 via `add_power_symbol_to_pin()`, which returns `pin_position` and `symbol_position` (the wire endpoints). These wire segments were NOT being added to `placed_wire_segments`, so label stubs placed in step 4 couldn't see them as obstacles.
|
||||||
|
|
||||||
|
Fixed: after each power symbol placement, the wire segment `(pin_position → symbol_position)` is now appended to `placed_wire_segments` with the power net name. Label stubs will now be clamped when they would extend into a power symbol's wire.
|
||||||
|
|
||||||
|
### R2 case (+3V3/SDA)
|
||||||
|
|
||||||
|
Pin 1's +3V3 power wire from (48.26, 145) to (48.26, ~137.38) is now tracked. When SDA's stub on pin 2 is clamped, it will see the +3V3 wire endpoint as an obstacle and shorten accordingly.
|
||||||
|
|
||||||
|
## Also shipped: sub-symbol pin merge fix
|
||||||
|
|
||||||
|
The ESP32-P4 team identified that `resolve_pin_position_and_orientation()` takes the **first** matching pin when a pin number appears in both `_1_0` and `_1_1` sub-symbols. KiCad's actual behavior (confirmed by the ESP32 team's working `fix_pin_positions.py`) uses the **last** definition (dict-overwrite semantics). Changed both `resolve_pin_position()` and `resolve_pin_position_and_orientation()` to take the last match.
|
||||||
|
|
||||||
|
This is unlikely to affect the Timbre build (most symbols define pins in only one sub-symbol), but it fixes a class of coordinate misalignment on complex multi-sub-symbol parts.
|
||||||
|
|
||||||
|
## What changed
|
||||||
|
|
||||||
|
- `src/mckicad/tools/batch.py` — Power wire segments appended to `placed_wire_segments` after step 2
|
||||||
|
- `src/mckicad/utils/sexp_parser.py` — Pin lookup takes last match instead of first (both resolve functions)
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- 350/350 tests pass
|
||||||
|
- ruff + mypy clean
|
||||||
|
|
||||||
|
## Expected outcome
|
||||||
|
|
||||||
|
After server restart, the +3V3/SDA and +5V/GND bridges should resolve. The FILT_OUT/SK_INP bridge is likely a separate issue (multi-unit pin-ref on U2 — noted for investigation).
|
||||||
@ -411,6 +411,16 @@ def _apply_batch_operations(
|
|||||||
stub_length=ps.get("stub_length"),
|
stub_length=ps.get("stub_length"),
|
||||||
)
|
)
|
||||||
placed_power.append(result)
|
placed_power.append(result)
|
||||||
|
# Track power wire stubs as obstacles for label clamping.
|
||||||
|
# Without this, label stubs can extend through power wires
|
||||||
|
# undetected (power symbols placed in step 2, labels in step 4).
|
||||||
|
pw_pin = result["pin_position"]
|
||||||
|
pw_sym = result["symbol_position"]
|
||||||
|
placed_wire_segments.append((
|
||||||
|
(pw_pin["x"], pw_pin["y"]),
|
||||||
|
(pw_sym["x"], pw_sym["y"]),
|
||||||
|
result["net"],
|
||||||
|
))
|
||||||
|
|
||||||
# 3. Wires
|
# 3. Wires
|
||||||
for wire in data.get("wires", []):
|
for wire in data.get("wires", []):
|
||||||
|
|||||||
@ -964,12 +964,13 @@ def resolve_pin_position(
|
|||||||
if not sexp_pins:
|
if not sexp_pins:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Find the matching pin
|
# Take the LAST matching pin across sub-symbols. KiCad lib_symbols
|
||||||
|
# may define the same pin in both _1_0 and _1_1 sub-symbols; the
|
||||||
|
# later definition takes precedence (dict-overwrite semantics).
|
||||||
target_pin = None
|
target_pin = None
|
||||||
for pin in sexp_pins:
|
for pin in sexp_pins:
|
||||||
if pin["number"] == pin_number:
|
if pin["number"] == pin_number:
|
||||||
target_pin = pin
|
target_pin = pin
|
||||||
break
|
|
||||||
|
|
||||||
if target_pin is None:
|
if target_pin is None:
|
||||||
return None
|
return None
|
||||||
@ -1092,11 +1093,11 @@ def resolve_pin_position_and_orientation(
|
|||||||
if not sexp_pins:
|
if not sexp_pins:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Take the LAST matching pin across sub-symbols (see resolve_pin_position)
|
||||||
target_pin = None
|
target_pin = None
|
||||||
for pin in sexp_pins:
|
for pin in sexp_pins:
|
||||||
if pin["number"] == pin_number:
|
if pin["number"] == pin_number:
|
||||||
target_pin = pin
|
target_pin = pin
|
||||||
break
|
|
||||||
|
|
||||||
if target_pin is None:
|
if target_pin is None:
|
||||||
return None
|
return None
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user