diff --git a/src/fn/pinrow.ts b/src/fn/pinrow.ts index 4c2cc389..bd2dee41 100644 --- a/src/fn/pinrow.ts +++ b/src/fn/pinrow.ts @@ -152,7 +152,9 @@ export const pinrow = ( break } } else { - const offset = od * 0.75 + // Keep through-hole pin labels beyond the outer edge of the plating. + // A fixed clearance remains effective for every supported pad diameter. + const offset = od / 2 + 0.6 switch (anchorSide) { case "right": dx = offset diff --git a/src/helpers/silkscreenPin.ts b/src/helpers/silkscreenPin.ts index d09fa5d3..e83cc9b4 100644 --- a/src/helpers/silkscreenPin.ts +++ b/src/helpers/silkscreenPin.ts @@ -11,6 +11,7 @@ export const silkscreenPin = ({ anchor_x, anchor_y, textalign = "center", + anchorplacement, orthogonal = false, verticallyinverted = false, layer = "top", @@ -37,13 +38,41 @@ export const silkscreenPin = ({ } let anchor_alignment: PcbSilkscreenText["anchor_alignment"] = "center" - if (textalign === "left") { - if (verticallyinverted) anchor_alignment = "center_right" - else anchor_alignment = "center_left" - } - if (textalign === "right") { - if (verticallyinverted) anchor_alignment = "center_left" - else anchor_alignment = "center_right" + if (textalign !== "center") { + const fallbackAlignment = + textalign === "left" + ? verticallyinverted + ? "center_right" + : "center_left" + : verticallyinverted + ? "center_left" + : "center_right" + + anchor_alignment = fallbackAlignment + + if (anchorplacement) { + const placementDirection = { + top: { x: 0, y: 1 }, + bottom: { x: 0, y: -1 }, + left: { x: -1, y: 0 }, + right: { x: 1, y: 0 }, + }[anchorplacement] + const rotationRadians = (ccw_rotation * Math.PI) / 180 + const textDirection = { + x: Math.cos(rotationRadians), + y: Math.sin(rotationRadians), + } + const directionDotProduct = + placementDirection.x * textDirection.x + + placementDirection.y * textDirection.y + + // Anchor the near edge of the label at the clearance point so rotated + // text extends away from the corresponding pad. + if (Math.abs(directionDotProduct) > 0.5) { + anchor_alignment = + directionDotProduct > 0 ? "center_left" : "center_right" + } + } } if (layer === "bottom") { diff --git a/tests/__snapshots__/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.snap.svg b/tests/__snapshots__/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.snap.svg index 167dc0bf..d3379e2c 100644 --- a/tests/__snapshots__/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN1}{PIN2}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN1}{PIN2}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow4_rows2_1.snap.svg b/tests/__snapshots__/pinrow4_rows2_1.snap.svg index bd575113..5aba9745 100644 --- a/tests/__snapshots__/pinrow4_rows2_1.snap.svg +++ b/tests/__snapshots__/pinrow4_rows2_1.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow4_vertical_column_labels_left.snap.svg b/tests/__snapshots__/pinrow4_vertical_column_labels_left.snap.svg new file mode 100644 index 00000000..c00e81dc --- /dev/null +++ b/tests/__snapshots__/pinrow4_vertical_column_labels_left.snap.svg @@ -0,0 +1 @@ +{PIN1}{PIN2}{PIN3}{PIN4}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow4_vertical_column_labels_right.snap.svg b/tests/__snapshots__/pinrow4_vertical_column_labels_right.snap.svg new file mode 100644 index 00000000..aa6f486d --- /dev/null +++ b/tests/__snapshots__/pinrow4_vertical_column_labels_right.snap.svg @@ -0,0 +1 @@ +{PIN1}{PIN2}{PIN3}{PIN4}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_1.snap.svg b/tests/__snapshots__/pinrow5_1.snap.svg index c7227793..64a9c711 100644 --- a/tests/__snapshots__/pinrow5_1.snap.svg +++ b/tests/__snapshots__/pinrow5_1.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_bottomsidepinlabel.snap.svg b/tests/__snapshots__/pinrow5_bottomsidepinlabel.snap.svg index 5c0a8478..27887965 100644 --- a/tests/__snapshots__/pinrow5_bottomsidepinlabel.snap.svg +++ b/tests/__snapshots__/pinrow5_bottomsidepinlabel.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_doublesidedpinlabel.snap.svg b/tests/__snapshots__/pinrow5_doublesidedpinlabel.snap.svg index 8a2d99e0..21ee6050 100644 --- a/tests/__snapshots__/pinrow5_doublesidedpinlabel.snap.svg +++ b/tests/__snapshots__/pinrow5_doublesidedpinlabel.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textaligncenter.snap.svg b/tests/__snapshots__/pinrow5_textaligncenter.snap.svg index c7227793..64a9c711 100644 --- a/tests/__snapshots__/pinrow5_textaligncenter.snap.svg +++ b/tests/__snapshots__/pinrow5_textaligncenter.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textaligncenter_orthogonal.snap.svg b/tests/__snapshots__/pinrow5_textaligncenter_orthogonal.snap.svg index 154ed2ef..63d5477b 100644 --- a/tests/__snapshots__/pinrow5_textaligncenter_orthogonal.snap.svg +++ b/tests/__snapshots__/pinrow5_textaligncenter_orthogonal.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textaligncenter_orthogonal_verticallyinverted.snap.svg b/tests/__snapshots__/pinrow5_textaligncenter_orthogonal_verticallyinverted.snap.svg index 3a52b7d3..10c7c7a6 100644 --- a/tests/__snapshots__/pinrow5_textaligncenter_orthogonal_verticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow5_textaligncenter_orthogonal_verticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textaligncenter_verticallyinverted.snap.svg b/tests/__snapshots__/pinrow5_textaligncenter_verticallyinverted.snap.svg index 5dffeb28..1a0857fe 100644 --- a/tests/__snapshots__/pinrow5_textaligncenter_verticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow5_textaligncenter_verticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignleft.snap.svg b/tests/__snapshots__/pinrow5_textalignleft.snap.svg index ac2d34e9..44ed958f 100644 --- a/tests/__snapshots__/pinrow5_textalignleft.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignleft.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignleft_orthogonal.snap.svg b/tests/__snapshots__/pinrow5_textalignleft_orthogonal.snap.svg index 6e3a7b40..ff3c0874 100644 --- a/tests/__snapshots__/pinrow5_textalignleft_orthogonal.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignleft_orthogonal.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignleft_orthogonal_verticallyinverted.snap.svg b/tests/__snapshots__/pinrow5_textalignleft_orthogonal_verticallyinverted.snap.svg index a33624bf..f1c17151 100644 --- a/tests/__snapshots__/pinrow5_textalignleft_orthogonal_verticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignleft_orthogonal_verticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignleft_verticallyinverted.snap.svg b/tests/__snapshots__/pinrow5_textalignleft_verticallyinverted.snap.svg index 2d81ec0f..3846e711 100644 --- a/tests/__snapshots__/pinrow5_textalignleft_verticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignleft_verticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignright.snap.svg b/tests/__snapshots__/pinrow5_textalignright.snap.svg index 51d141f8..34f09669 100644 --- a/tests/__snapshots__/pinrow5_textalignright.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignright.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignright_orthogonal.snap.svg b/tests/__snapshots__/pinrow5_textalignright_orthogonal.snap.svg index b7cf8ead..442f6e10 100644 --- a/tests/__snapshots__/pinrow5_textalignright_orthogonal.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignright_orthogonal.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignright_orthogonal_verticallyinverted.snap.svg b/tests/__snapshots__/pinrow5_textalignright_orthogonal_verticallyinverted.snap.svg index b8c26b7b..a75991b8 100644 --- a/tests/__snapshots__/pinrow5_textalignright_orthogonal_verticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignright_orthogonal_verticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow5_textalignright_verticallyinverted.snap.svg b/tests/__snapshots__/pinrow5_textalignright_verticallyinverted.snap.svg index c15d6fe4..2ff54559 100644 --- a/tests/__snapshots__/pinrow5_textalignright_verticallyinverted.snap.svg +++ b/tests/__snapshots__/pinrow5_textalignright_verticallyinverted.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow6_female_rows2_1.snap.svg b/tests/__snapshots__/pinrow6_female_rows2_1.snap.svg index 75701f10..7b535873 100644 --- a/tests/__snapshots__/pinrow6_female_rows2_1.snap.svg +++ b/tests/__snapshots__/pinrow6_female_rows2_1.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow6_nosquareplating_1.snap.svg b/tests/__snapshots__/pinrow6_nosquareplating_1.snap.svg index df38d0bd..d472c839 100644 --- a/tests/__snapshots__/pinrow6_nosquareplating_1.snap.svg +++ b/tests/__snapshots__/pinrow6_nosquareplating_1.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow8_rows4_1.snap.svg b/tests/__snapshots__/pinrow8_rows4_1.snap.svg index c5ab6094..e572462d 100644 --- a/tests/__snapshots__/pinrow8_rows4_1.snap.svg +++ b/tests/__snapshots__/pinrow8_rows4_1.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{PIN7}{PIN8}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{PIN7}{PIN8}{REF} \ No newline at end of file diff --git a/tests/__snapshots__/pinrow9_male_rows3_1.snap.svg b/tests/__snapshots__/pinrow9_male_rows3_1.snap.svg index 822bd4e8..14fb88c0 100644 --- a/tests/__snapshots__/pinrow9_male_rows3_1.snap.svg +++ b/tests/__snapshots__/pinrow9_male_rows3_1.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{PIN7}{PIN8}{PIN9}{REF} \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{PIN7}{PIN8}{PIN9}{REF} \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/pinrow.snap.svg b/tests/kicad-parity/__snapshots__/pinrow.snap.svg index 0675e011..87808557 100644 --- a/tests/kicad-parity/__snapshots__/pinrow.snap.svg +++ b/tests/kicad-parity/__snapshots__/pinrow.snap.svg @@ -1 +1 @@ -{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{REF}REF**Diff: 0.00% \ No newline at end of file +{PIN1}{PIN2}{PIN3}{PIN4}{PIN5}{PIN6}{REF}REF**Diff: 0.00% \ No newline at end of file diff --git a/tests/pinrow.test.ts b/tests/pinrow.test.ts index 21b1d1fb..149d7782 100644 --- a/tests/pinrow.test.ts +++ b/tests/pinrow.test.ts @@ -58,6 +58,57 @@ test("pinrow4_rows2 geometry is centered on origin", () => { expect(refText?.anchor_position).toEqual({ x: 0, y: 3.81 }) }) +const verticalColumnLabelCases = [ + { + side: "left", + definition: "pinrow4_rows4_nosquareplating_pinlabeltextalignright", + expectedX: -1.35, + anchorAlignment: "center_right", + }, + { + side: "right", + definition: "pinrow4_rows4_nosquareplating_pinlabeltextalignleft", + expectedX: 1.35, + anchorAlignment: "center_left", + }, +] as const + +for (const { + side, + definition, + expectedX, + anchorAlignment, +} of verticalColumnLabelCases) { + test(`vertical pin column keeps labels on the ${side} of plated holes`, () => { + const circuitJson = fp.string(definition).circuitJson() + const svgContent = convertCircuitJsonToPcbSvg(circuitJson) + const platedHoles = circuitJson.filter( + (element) => element.type === "pcb_plated_hole", + ) + const pinLabels = circuitJson.filter( + (element) => + element.type === "pcb_silkscreen_text" && + element.text.startsWith("{PIN"), + ) + const pinYs = [3.81, 1.27, -1.27, -3.81] + + expect(platedHoles.map(({ x, y }) => ({ x, y }))).toEqual( + pinYs.map((y) => ({ x: 0, y })), + ) + expect(pinLabels).toMatchObject( + pinYs.map((y, index) => ({ + text: `{PIN${index + 1}}`, + anchor_position: { x: expectedX, y }, + anchor_alignment: anchorAlignment, + })), + ) + expect(svgContent).toMatchSvgSnapshot( + import.meta.path, + `pinrow4_vertical_column_labels_${side}`, + ) + }) +} + test("pinrow8_rows4", () => { const circuitJson = fp.string("pinrow8_rows4").circuitJson() const svgContent = convertCircuitJsonToPcbSvg(circuitJson) @@ -152,7 +203,6 @@ test("pinrow6_nosquareplating", () => { "pinrow6_nosquareplating_1", ) }) - const textAlignments = ["left", "center", "right"] as const const orthogonalStates = [ { name: "", value: false }, diff --git a/tests/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.test.ts b/tests/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.test.ts index 55456e19..34d0881a 100644 --- a/tests/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.test.ts +++ b/tests/pinrow2_id1.016_od1.88_nosquareplating_pinlabeltextalignright_pinlabelorthogonal_doublesidedpinlabel_pinlabelverticallyinverted.test.ts @@ -53,29 +53,29 @@ test(def, () => { { text: "{PIN1}", layer: "top", - anchor_position: { x: -1.27, y: 1.41 }, - anchor_alignment: "center_left", + anchor_position: { x: -1.27, y: 1.54 }, + anchor_alignment: "center_right", ccw_rotation: 270, }, { text: "{PIN1}", layer: "bottom", - anchor_position: { x: -1.27, y: 1.41 }, - anchor_alignment: "center_right", + anchor_position: { x: -1.27, y: 1.54 }, + anchor_alignment: "center_left", ccw_rotation: 270, }, { text: "{PIN2}", layer: "top", - anchor_position: { x: 1.27, y: 1.41 }, - anchor_alignment: "center_left", + anchor_position: { x: 1.27, y: 1.54 }, + anchor_alignment: "center_right", ccw_rotation: 270, }, { text: "{PIN2}", layer: "bottom", - anchor_position: { x: 1.27, y: 1.41 }, - anchor_alignment: "center_right", + anchor_position: { x: 1.27, y: 1.54 }, + anchor_alignment: "center_left", ccw_rotation: 270, }, ])