fix: apply unannotated-reference fix to find_unconnected_pins and get_elements_in_region

The same reference-lookup bug fixed in check_wire_collisions (where
PinLocator.get_all_symbol_pins always resolves to the first symbol
with a given reference) also affected:

- find_unconnected_pins: would check wrong pin positions for all
  unannotated components after the first, producing false connected/
  unconnected reports.
- get_elements_in_region: would return wrong pin coordinates for
  unannotated components in the queried region.

Both now use _compute_pin_positions_direct (fetching pin defs by
lib_id and applying each symbol's own position/rotation/mirror),
matching the fix already applied to check_wire_collisions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Eugene Mikhantyev
2026-03-15 11:06:08 +00:00
parent 53564cbc58
commit 1bfa608729

View File

@@ -293,11 +293,13 @@ def find_unconnected_pins(schematic_path: Path) -> List[Dict[str, Any]]:
if sym["is_power"] or ref.startswith("_TEMPLATE") or not ref: if sym["is_power"] or ref.startswith("_TEMPLATE") or not ref:
continue continue
pin_positions = locator.get_all_symbol_pins(schematic_path, ref) pin_defs = locator.get_symbol_pins(schematic_path, sym["lib_id"])
if not pin_positions: if not pin_defs:
continue continue
pin_defs = None pin_positions = _compute_pin_positions_direct(sym, pin_defs)
if not pin_positions:
continue
for pin_num, pos in pin_positions.items(): for pin_num, pos in pin_positions.items():
px, py = pos[0], pos[1] px, py = pos[0], pos[1]
@@ -307,9 +309,6 @@ def find_unconnected_pins(schematic_path: Path) -> List[Dict[str, Any]]:
if is_connected(px, py): if is_connected(px, py):
continue continue
if pin_defs is None:
pin_defs = locator.get_symbol_pins(schematic_path, sym["lib_id"])
pin_name = pin_defs.get(pin_num, {}).get("name", pin_num) pin_name = pin_defs.get(pin_num, {}).get("name", pin_num)
unconnected.append({ unconnected.append({
"reference": ref, "reference": ref,
@@ -482,13 +481,15 @@ def get_elements_in_region(
"position": {"x": sym["x"], "y": sym["y"]}, "position": {"x": sym["x"], "y": sym["y"]},
"isPower": sym["is_power"], "isPower": sym["is_power"],
} }
# Include pin positions # Include pin positions (compute directly to handle unannotated duplicates)
pin_positions = locator.get_all_symbol_pins(schematic_path, sym["reference"]) pin_defs = locator.get_symbol_pins(schematic_path, sym["lib_id"])
if pin_positions: if pin_defs:
entry["pins"] = { pin_positions = _compute_pin_positions_direct(sym, pin_defs)
pn: {"x": round(pos[0], 4), "y": round(pos[1], 4)} if pin_positions:
for pn, pos in pin_positions.items() entry["pins"] = {
} pn: {"x": round(pos[0], 4), "y": round(pos[1], 4)}
for pn, pos in pin_positions.items()
}
region_symbols.append(entry) region_symbols.append(entry)
# Wires: include if ANY endpoint is within bounds # Wires: include if ANY endpoint is within bounds