diff --git a/src/mckicad/utils/sexp_parser.py b/src/mckicad/utils/sexp_parser.py index 0facfd7..d2bf271 100644 --- a/src/mckicad/utils/sexp_parser.py +++ b/src/mckicad/utils/sexp_parser.py @@ -1128,11 +1128,22 @@ def resolve_pin_position_and_orientation( target_pin["x"], target_pin["y"], cx, cy, comp_rot, mirror_x, ) - # Compute schematic-space pin rotation + # Compute schematic-space pin rotation. + # Pin angles in lib_symbol use Y-up convention. After applying the + # component rotation, vertical directions must be swapped (90 <-> 270) + # to account for the lib Y-up -> schematic Y-down coordinate flip. + # For mirrored components, the mirror is applied first. pin_rot = target_pin["rotation"] if mirror_x: pin_rot = (180 - pin_rot) % 360 schematic_rot = (pin_rot + comp_rot) % 360 + # Y-flip: swap vertical directions for non-mirrored components. + # Mirror already handles the inversion via (180 - pin_rot). + if not mirror_x: + if schematic_rot == 90: + schematic_rot = 270 + elif schematic_rot == 270: + schematic_rot = 90 logger.debug( "Resolved pin %s.%s via sexp fallback: (%.2f, %.2f) @ %.0f°",