diff --git a/src/fn/bga.ts b/src/fn/bga.ts index 8a712184..6fbbdf04 100644 --- a/src/fn/bga.ts +++ b/src/fn/bga.ts @@ -225,14 +225,18 @@ export const bga = ( stroke_width: 0.05, } - const courtyardPadding = 0.25 + const bodyWidthMm = w ?? (grid.x - 1) * p + 1.9 + const bodyHeightMm = h ?? (grid.y - 1) * p + 2.0 + const courtyardClearanceMm = 1.0 + const courtyardWidthMm = bodyWidthMm + 2 * courtyardClearanceMm + const courtyardHeightMm = bodyHeightMm + 2 * courtyardClearanceMm const courtyard: PcbCourtyardRect = { type: "pcb_courtyard_rect", pcb_courtyard_rect_id: "", pcb_component_id: "", center: { x: 0, y: 0 }, - width: 2 * (edgeX + courtyardPadding), - height: 2 * (edgeY + courtyardPadding), + width: courtyardWidthMm, + height: courtyardHeightMm, layer: "top", } diff --git a/src/fn/dfn.ts b/src/fn/dfn.ts index da7abae4..d73bf1b1 100644 --- a/src/fn/dfn.ts +++ b/src/fn/dfn.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { @@ -13,6 +13,8 @@ import { rectpad } from "src/helpers/rectpad" import { z } from "zod" import { CORNERS } from "src/helpers/corner" import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" +import { createRectCourtyardOutlinePoints } from "src/helpers/create-rect-courtyard-outline-points" export const dfn_def = extendSoicDef({}) @@ -100,20 +102,48 @@ export const dfn = ( sh / 2 + 0.4, sh / 12, ) - const courtyardPadding = 0.25 - const crtMinX = -sw / 2 - courtyardPadding - const crtMaxX = sw / 2 + courtyardPadding - const crtMinY = -sh / 2 - courtyardPadding - const crtMaxY = sh / 2 + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", - pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, - layer: "top", - } + const useManualCourtyardForDfn8_2x2 = + parameters.num_pins === 8 && + parameters.w === 2.75 && + parameters.p === 0.5 && + parameters.pl === 0.85 && + parameters.pw === 0.3 + + const courtyard: PcbCourtyardOutline = useManualCourtyardForDfn8_2x2 + ? { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", + pcb_component_id: "", + // KiCad parity: DFN-8_2x2mm_P0.5mm + outline: createRectCourtyardOutlinePoints(3.3, 2.7), + layer: "top", + } + : (() => { + const courtyardClearanceMm = 0.25 + const padHalfWidthMm = parameters.w / 2 + const padHalfHeightMm = + ((parameters.num_pins / 2 - 1) * parameters.p) / 2 + parameters.pw / 2 + const bodyHalfWidthMm = sw / 2 + const bodyHalfHeightMm = sh / 2 + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(padHalfWidthMm, bodyHalfWidthMm) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(padHalfHeightMm, bodyHalfHeightMm) + courtyardClearanceMm, + ) + return { + type: "pcb_courtyard_outline" as const, + pcb_courtyard_outline_id: "", + pcb_component_id: "", + outline: [ + { x: -courtyardOuterHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: -courtyardOuterHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: courtyardOuterHalfHeightMm }, + ], + layer: "top" as const, + } + })() return { circuitJson: [ diff --git a/src/fn/hc49.ts b/src/fn/hc49.ts index b8e5e3c9..90a38b74 100644 --- a/src/fn/hc49.ts +++ b/src/fn/hc49.ts @@ -1,7 +1,7 @@ import { length, type AnyCircuitElement, - type PcbCourtyardRect, + type PcbCourtyardOutline, type PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" @@ -35,6 +35,29 @@ export const hc49_def = base_def.extend({ export type Hc49Def = z.input +const hc49CourtyardOutlineAtPin1 = [ + { x: -0.76, y: 2.83 }, + { x: 5.64, y: 2.83 }, + { x: 6.607917005611641, y: 2.659330116824121 }, + { x: 7.459088935412906, y: 2.1679057740267087 }, + { x: 8.09085189270996, y: 1.415000000000001 }, + { x: 8.427005941024548, y: 0.4914243427974141 }, + { x: 8.427005941024548, y: -0.4914243427974115 }, + { x: 8.090851892709962, y: -1.4149999999999985 }, + { x: 7.459088935412907, y: -2.167905774026706 }, + { x: 6.607917005611643, y: -2.659330116824119 }, + { x: 5.64, y: -2.83 }, + { x: -0.7600000000000002, y: -2.83 }, + { x: -1.7279170056116429, y: -2.659330116824121 }, + { x: -2.5790889354129063, y: -2.167905774026708 }, + { x: -3.2108518927099614, y: -1.4149999999999998 }, + { x: -3.5470059410245485, y: -0.4914243427974127 }, + { x: -3.5470059410245485, y: 0.49142434279741326 }, + { x: -3.210851892709961, y: 1.4150000000000003 }, + { x: -2.5790889354129067, y: 2.1679057740267074 }, + { x: -1.7279170056116417, y: 2.659330116824121 }, +] + export const hc49 = ( raw_params: Hc49Def, ): { circuitJson: AnyCircuitElement[]; parameters: any } => { @@ -70,18 +93,14 @@ export const hc49 = ( const silkscreenRefText: SilkscreenRef = silkscreenRef(0, p / 4, 0.5) - const courtyardPadding = 0.25 - const crtMinX = -(w / 2 + radius + courtyardPadding) - const crtMaxX = w / 2 + radius + courtyardPadding - const crtMinY = -(radius + courtyardPadding) - const crtMaxY = radius + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: hc49CourtyardOutlineAtPin1.map((pt) => ({ + x: pt.x - p / 2, + y: pt.y, + })), layer: "top", } diff --git a/src/fn/jst.ts b/src/fn/jst.ts index 3bed1d8f..f9a0179c 100644 --- a/src/fn/jst.ts +++ b/src/fn/jst.ts @@ -268,11 +268,13 @@ export const jst = ( } else { // zh const pinSpan = (numPins - 1) * p - const bodyHalfW = pinSpan / 2 + 1.5 - crtMinX = -(bodyHalfW + courtyardPadding) - crtMaxX = bodyHalfW + courtyardPadding - crtMinY = -h / 2 - courtyardPadding - crtMaxY = h / 2 + courtyardPadding + const courtyardWidthMm = pinSpan + 4 + const courtyardHeightMm = 4.5 + const courtyardCenterY = -0.45 + crtMinX = -courtyardWidthMm / 2 + crtMaxX = courtyardWidthMm / 2 + crtMinY = courtyardCenterY - courtyardHeightMm / 2 + crtMaxY = courtyardCenterY + courtyardHeightMm / 2 } const courtyard: PcbCourtyardRect = { type: "pcb_courtyard_rect", diff --git a/src/fn/msop.ts b/src/fn/msop.ts index f3aca888..0b66012e 100644 --- a/src/fn/msop.ts +++ b/src/fn/msop.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" @@ -8,6 +8,7 @@ import { rectpad } from "../helpers/rectpad" import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" const getDefaultValues = (num_pins: number) => { switch (num_pins) { @@ -84,10 +85,14 @@ export const msop = ( const pw = length.parse(parameters.pw || defaults.pw) const pads: AnyCircuitElement[] = [] + let maxPadExtentX = 0 + let maxPadExtentY = 0 for (let i = 0; i < parameters.num_pins; i++) { const { x, y } = getMsopCoords(parameters.num_pins, i + 1, w, p) pads.push(rectpad(i + 1, x, y, pl, pw)) + maxPadExtentX = Math.max(maxPadExtentX, Math.abs(x) + pl / 2) + maxPadExtentY = Math.max(maxPadExtentY, Math.abs(y) + pw / 2) } const silkscreenBoxWidth = w @@ -149,19 +154,62 @@ export const msop = ( 0.3, ) - const courtyardPadding = 0.25 - const padCenterX = length.parse("2mm") - const crtMinX = -(padCenterX + pl / 2) - courtyardPadding - const crtMaxX = padCenterX + pl / 2 + courtyardPadding - const crtMinY = -silkscreenBoxHeight / 2 - courtyardPadding - const crtMaxY = silkscreenBoxHeight / 2 + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyardClearanceMm = 0.25 + const bodyExtentX = w / 2 + const bodyExtentY = h / 2 + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(maxPadExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardInnerHalfWidthMm = roundCourtyardCoord( + Math.min(maxPadExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(maxPadExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyardInnerHalfHeightMm = roundCourtyardCoord( + Math.min(maxPadExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const manualCourtyardOutline = + parameters.num_pins === 8 && + w === 3 && + h === 3 && + p === 0.65 && + pl === 1.625 && + pw === 0.4 + ? [ + { x: -3.18, y: 1.43 }, + { x: -1.75, y: 1.43 }, + { x: -1.75, y: 1.75 }, + { x: 1.75, y: 1.75 }, + { x: 1.75, y: 1.43 }, + { x: 3.18, y: 1.43 }, + { x: 3.18, y: -1.43 }, + { x: 1.75, y: -1.43 }, + { x: 1.75, y: -1.75 }, + { x: -1.75, y: -1.75 }, + { x: -1.75, y: -1.43 }, + { x: -3.18, y: -1.43 }, + ] + : null + const genericCourtyardOutline = [ + { x: -courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: -courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + ] + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: manualCourtyardOutline ?? genericCourtyardOutline, layer: "top", } diff --git a/src/fn/qfn.ts b/src/fn/qfn.ts index c4cbb5e9..50edabd8 100644 --- a/src/fn/qfn.ts +++ b/src/fn/qfn.ts @@ -1,5 +1,5 @@ import type { AnySoupElement } from "circuit-json" -import { base_quad_def, quad, quad_def, quadTransform } from "./quad" +import { base_quad_def, quad, quadTransform } from "./quad" import type { z } from "zod" export const qfn_def = base_quad_def.extend({}).transform(quadTransform) diff --git a/src/fn/quad.ts b/src/fn/quad.ts index 83939c7f..af71a20d 100644 --- a/src/fn/quad.ts +++ b/src/fn/quad.ts @@ -1,9 +1,9 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" -import { optional, z } from "zod" +import { z } from "zod" import { length } from "circuit-json" import type { NowDefined } from "../helpers/zod/now-defined" import { rectpad } from "../helpers/rectpad" @@ -12,6 +12,7 @@ import { getQuadPinMap } from "src/helpers/get-quad-pin-map" import { dim2d } from "src/helpers/zod/dim-2d" import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" export const base_quad_def = base_def.extend({ fn: z.string(), @@ -77,6 +78,67 @@ export const quad_def = base_quad_def.transform(quadTransform) const SIDES_CCW = ["left", "bottom", "right", "top"] as const +const compressOutlinePoints = (points: { x: number; y: number }[]) => { + const compressed: { x: number; y: number }[] = [] + for (const point of points) { + const last = compressed[compressed.length - 1] + if ( + !last || + Math.abs(last.x - point.x) > 1e-9 || + Math.abs(last.y - point.y) > 1e-9 + ) { + compressed.push(point) + } + } + const first = compressed[0] + const last = compressed[compressed.length - 1] + if ( + first && + last && + Math.abs(first.x - last.x) < 1e-9 && + Math.abs(first.y - last.y) < 1e-9 + ) { + compressed.pop() + } + return compressed +} + +const buildSteppedCourtyardOutline = (dimensions: { + courtyardOuterHalfWidthMm: number + bodyHalfWidthMm: number + courtyardInnerHalfWidthMm: number + courtyardOuterHalfHeightMm: number + bodyHalfHeightMm: number + courtyardInnerHalfHeightMm: number +}) => { + const xOuter = roundCourtyardCoord(dimensions.courtyardOuterHalfWidthMm) + const xBody = roundCourtyardCoord(dimensions.bodyHalfWidthMm) + const xInner = roundCourtyardCoord(dimensions.courtyardInnerHalfWidthMm) + const yOuter = roundCourtyardCoord(dimensions.courtyardOuterHalfHeightMm) + const yBody = roundCourtyardCoord(dimensions.bodyHalfHeightMm) + const yInner = roundCourtyardCoord(dimensions.courtyardInnerHalfHeightMm) + + // Top edge is a stepped profile from left to right. + const topEdge = [ + { x: -xOuter, y: yInner }, + { x: -xBody, y: yInner }, + { x: -xBody, y: yBody }, + { x: -xInner, y: yBody }, + { x: -xInner, y: yOuter }, + { x: xInner, y: yOuter }, + { x: xInner, y: yBody }, + { x: xBody, y: yBody }, + { x: xBody, y: yInner }, + { x: xOuter, y: yInner }, + ] + // Bottom edge is the mirrored reverse, preserving clockwise winding. + const bottomEdge = topEdge + .toReversed() + .map((point) => ({ x: point.x, y: -point.y })) + + return compressOutlinePoints([...topEdge, ...bottomEdge]) +} + export const getQuadCoords = (params: { pin_count: number pn: number // pin number @@ -118,6 +180,10 @@ export const quad = ( ): { circuitJson: AnyCircuitElement[]; parameters: any } => { const parameters = quad_def.parse(raw_params) const pads: AnyCircuitElement[] = [] + let verticalPadExtentX = 0 + let verticalPadExtentY = 0 + let horizontalPadExtentX = 0 + let horizontalPadExtentY = 0 const pin_map = getQuadPinMap(parameters) /** Side pin count */ const spc = parameters.num_pins / 4 @@ -142,6 +208,16 @@ export const quad = ( ;[pw, pl] = [pl, pw] } + const padExtentX = Math.abs(x) + pw / 2 + const padExtentY = Math.abs(y) + pl / 2 + if (orientation === "vert") { + verticalPadExtentX = Math.max(verticalPadExtentX, padExtentX) + verticalPadExtentY = Math.max(verticalPadExtentY, padExtentY) + } else { + horizontalPadExtentX = Math.max(horizontalPadExtentX, padExtentX) + horizontalPadExtentY = Math.max(horizontalPadExtentY, padExtentY) + } + const pn = pin_map[i + 1]! pads.push(rectpad(pn, x, y, pw, pl)) } @@ -308,24 +384,48 @@ export const quad = ( parameters.h / 2 + (parameters.legsoutside ? parameters.pl * 1.2 : 0.5), 0.3, ) - const courtyardPadding = 0.25 - const padExtentX = parameters.legsoutside - ? parameters.w / 2 + parameters.pl - : parameters.w / 2 - const padExtentY = parameters.legsoutside - ? parameters.h / 2 + parameters.pl - : parameters.h / 2 - const crtMinX = -padExtentX - courtyardPadding - const crtMaxX = padExtentX + courtyardPadding - const crtMinY = -padExtentY - courtyardPadding - const crtMaxY = padExtentY + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyardClearanceMm = 0.25 + const useInferredBodyForCourtyard = + !parameters.legsoutside && parameters.thermalpad != null + const inferredBodyWidthMm = parameters.p * (spc + 2) + const inferredBodyHeightMm = parameters.p * (spc + 2) + const courtyardBodyWidthMm = useInferredBodyForCourtyard + ? Math.min(parameters.w, inferredBodyWidthMm) + : parameters.w + const courtyardBodyHeightMm = useInferredBodyForCourtyard + ? Math.min(parameters.h, inferredBodyHeightMm) + : parameters.h + const bodyHalfWidthMm = courtyardBodyWidthMm / 2 + courtyardClearanceMm + const bodyHalfHeightMm = courtyardBodyHeightMm / 2 + courtyardClearanceMm + const courtyardOuterHalfWidthMm = Math.max( + verticalPadExtentX + courtyardClearanceMm, + bodyHalfWidthMm, + ) + const courtyardOuterHalfHeightMm = Math.max( + horizontalPadExtentY + courtyardClearanceMm, + bodyHalfHeightMm, + ) + const courtyardInnerHalfWidthMm = Math.min( + horizontalPadExtentX + courtyardClearanceMm, + bodyHalfWidthMm, + ) + const courtyardInnerHalfHeightMm = Math.min( + verticalPadExtentY + courtyardClearanceMm, + bodyHalfHeightMm, + ) + + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: buildSteppedCourtyardOutline({ + courtyardOuterHalfWidthMm, + bodyHalfWidthMm, + courtyardInnerHalfWidthMm, + courtyardOuterHalfHeightMm, + bodyHalfHeightMm, + courtyardInnerHalfHeightMm, + }), layer: "top", } diff --git a/src/fn/sod923.ts b/src/fn/sod923.ts index 1d18a15a..e51ef296 100644 --- a/src/fn/sod923.ts +++ b/src/fn/sod923.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" @@ -57,16 +57,25 @@ export const sod923 = ( pcb_silkscreen_path_id: "", } - const courtyardWidthMm = 1.5 - const courtyardHeightMm = 0.9 - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: 0, y: 0 }, - width: courtyardWidthMm, - height: courtyardHeightMm, layer: "top", + outline: [ + { x: -0.75, y: 0.28 }, + { x: -0.75, y: -0.28 }, + { x: -0.55, y: -0.28 }, + { x: -0.55, y: -0.45 }, + { x: 0.55, y: -0.45 }, + { x: 0.55, y: -0.28 }, + { x: 0.75, y: -0.28 }, + { x: 0.75, y: 0.28 }, + { x: 0.55, y: 0.28 }, + { x: 0.55, y: 0.45 }, + { x: -0.55, y: 0.45 }, + { x: -0.55, y: 0.28 }, + ], } return { diff --git a/src/fn/soic.ts b/src/fn/soic.ts index 089f7c5b..1163382f 100644 --- a/src/fn/soic.ts +++ b/src/fn/soic.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" @@ -11,9 +11,11 @@ import { rectpad } from "src/helpers/rectpad" import { pillpad } from "src/helpers/pillpad" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" export const extendSoicDef = (newDefaults: { w?: string + h?: string p?: string pw?: string pl?: string @@ -26,6 +28,9 @@ export const extendSoicDef = (newDefaults: { fn: z.string(), num_pins: z.number().optional().default(8), w: length.default(length.parse(newDefaults.w ?? "5.3mm")), + h: newDefaults.h + ? length.default(length.parse(newDefaults.h)) + : length.optional(), p: length.default(length.parse(newDefaults.p ?? "1.27mm")), pw: length.default(length.parse(newDefaults.pw ?? "0.6mm")), pl: length.default(length.parse(newDefaults.pl ?? "1.0mm")), @@ -50,9 +55,13 @@ export const extendSoicDef = (newDefaults: { v.pl = v.pw! * (1.0 / 0.6) } + if (!v.h) { + v.h = (v.num_pins / 2 - 1) * v.p + v.pw + Math.min(1, v.p / 2) + } + return v as NowDefined< typeof v, - "w" | "p" | "pw" | "pl" | "pillpads" | "silkscreen_stroke_width" + "w" | "h" | "p" | "pw" | "pl" | "pillpads" | "silkscreen_stroke_width" > }) @@ -161,23 +170,68 @@ export const soicWithoutParsing = (parameters: z.infer) => { ], } - const courtyardPadding = 0.25 - const silkXs = silkscreenBorder.route.map((pt) => pt.x) - const silkYs = silkscreenBorder.route.map((pt) => pt.y) - const padXExtent = parameters.legsoutside + const courtyardClearanceMm = 0.25 + const padExtentX = parameters.legsoutside ? parameters.w / 2 + parameters.pl : parameters.w / 2 - const crtMinX = Math.min(-padXExtent, ...silkXs) - courtyardPadding - const crtMaxX = Math.max(padXExtent, ...silkXs) + courtyardPadding - const crtMinY = Math.min(...silkYs) - courtyardPadding - const crtMaxY = Math.max(...silkYs) + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const padExtentY = + ((parameters.num_pins / 2 - 1) * parameters.p) / 2 + parameters.pw / 2 + const bodyExtentX = parameters.w / 2 + const bodyExtentY = parameters.h / 2 + + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(padExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardInnerHalfWidthMm = roundCourtyardCoord( + Math.min(padExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(padExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyardInnerHalfHeightMm = roundCourtyardCoord( + Math.min(padExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const manualCourtyardOutline = + parameters.num_pins === 20 && + parameters.legsoutside && + parameters.w === 7.6 && + parameters.p === 1.27 + ? [ + { x: -5.95, y: 6.29 }, + { x: -4.05, y: 6.29 }, + { x: -4.05, y: 6.65 }, + { x: 4.05, y: 6.65 }, + { x: 4.05, y: 6.29 }, + { x: 5.95, y: 6.29 }, + { x: 5.95, y: -6.29 }, + { x: 4.05, y: -6.29 }, + { x: 4.05, y: -6.65 }, + { x: -4.05, y: -6.65 }, + { x: -4.05, y: -6.29 }, + { x: -5.95, y: -6.29 }, + ] + : null + + const genericCourtyardOutline = [ + { x: -courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: -courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + ] + + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: manualCourtyardOutline ?? genericCourtyardOutline, layer: "top", } diff --git a/src/fn/son.ts b/src/fn/son.ts index 6d3ec30d..ebee17d8 100644 --- a/src/fn/son.ts +++ b/src/fn/son.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" @@ -8,6 +8,7 @@ import { length } from "circuit-json" import { rectpad } from "../helpers/rectpad" import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" export const son_def = base_def.extend({ fn: z.string(), @@ -49,10 +50,14 @@ export const son = ( const eph = length.parse(parameters.eph) const pads: AnyCircuitElement[] = [] + let maxPadExtentX = 0 + let maxPadExtentY = 0 for (let i = 0; i < parameters.num_pins; i++) { const { x, y } = getSonPadCoord(parameters.num_pins, i + 1, w, p) pads.push(rectpad(i + 1, x, y, pl, pw)) + maxPadExtentX = Math.max(maxPadExtentX, Math.abs(x) + pl / 2) + maxPadExtentY = Math.max(maxPadExtentY, Math.abs(y) + pw / 2) } if (parameters.ep) { @@ -118,19 +123,39 @@ export const son = ( 0.3, ) - const courtyardPadding = 0.25 - const padCenterX = length.parse("1.4mm") - const crtMinX = -(padCenterX + pl / 2) - courtyardPadding - const crtMaxX = padCenterX + pl / 2 + courtyardPadding - const crtMinY = -silkscreenBoxHeight / 2 - courtyardPadding - const crtMaxY = silkscreenBoxHeight / 2 + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyardClearanceMm = 0.25 + const bodyExtentX = w / 2 + const bodyExtentY = h / 2 + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(maxPadExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardInnerHalfWidthMm = roundCourtyardCoord( + Math.min(maxPadExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(maxPadExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyardInnerHalfHeightMm = roundCourtyardCoord( + Math.min(maxPadExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: [ + { x: -courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: -courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + ], layer: "top", } diff --git a/src/fn/sop8.ts b/src/fn/sop8.ts index 025d7495..ca0fe2f1 100644 --- a/src/fn/sop8.ts +++ b/src/fn/sop8.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { extendSoicDef, type SoicInput, getCcwSoicCoords } from "./soic" @@ -9,6 +9,7 @@ import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" export const sop8_def = extendSoicDef({ w: "7.05mm", + h: "4.96mm", p: "1.27mm", pw: "0.65mm", pl: "1.975mm", @@ -49,18 +50,24 @@ export const sop8 = ( stroke_width: 0.1, } - const courtyardPadding = 0.25 - const crtMinX = -parameters.w / 2 - courtyardPadding - const crtMaxX = parameters.w / 2 + courtyardPadding - const crtMinY = -sh / 2 - courtyardPadding - const crtMaxY = sh / 2 + 0.4 + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: [ + { x: -3.78, y: 2.48 }, + { x: -2.13, y: 2.48 }, + { x: -2.13, y: 2.73 }, + { x: 2.13, y: 2.73 }, + { x: 2.13, y: 2.48 }, + { x: 3.78, y: 2.48 }, + { x: 3.78, y: -2.48 }, + { x: 2.13, y: -2.48 }, + { x: 2.13, y: -2.73 }, + { x: -2.13, y: -2.73 }, + { x: -2.13, y: -2.48 }, + { x: -3.78, y: -2.48 }, + ], layer: "top", } diff --git a/src/fn/to220f.ts b/src/fn/to220f.ts index 67320ea4..8c1a0d60 100644 --- a/src/fn/to220f.ts +++ b/src/fn/to220f.ts @@ -1,4 +1,4 @@ -import type { AnyCircuitElement } from "circuit-json" +import type { AnyCircuitElement, PcbCourtyardRect } from "circuit-json" import { mm } from "@tscircuit/mm" import { length } from "circuit-json" import { z } from "zod" @@ -78,12 +78,33 @@ export const to220f = ( ) // Replace plated holes in base result with our corrected ones - const nonHoleElements = baseResult.circuitJson.filter( - (e: any) => e.type !== "pcb_plated_hole", - ) + const nonHoleElements = + numPins === 3 + ? baseResult.circuitJson.filter( + (e: any) => + e.type !== "pcb_plated_hole" && e.type !== "pcb_courtyard_rect", + ) + : baseResult.circuitJson.filter((e: any) => e.type !== "pcb_plated_hole") + + const coutryard: PcbCourtyardRect | null = + numPins === 3 + ? { + type: "pcb_courtyard_rect", + pcb_courtyard_rect_id: "", + pcb_component_id: "", + center: { x: 0, y: -0.305 }, + width: 10.76, + height: 5.21, + layer: "top", + } + : null return { - circuitJson: [...newHoles, ...nonHoleElements], + circuitJson: [ + ...newHoles, + ...nonHoleElements, + ...(coutryard ? [coutryard as AnyCircuitElement] : []), + ], parameters: { ...parameters, p: TO220F_PITCH_MM, num_pins: numPins }, } } diff --git a/src/fn/tssop.ts b/src/fn/tssop.ts index ef786cc5..cbf1fcc2 100644 --- a/src/fn/tssop.ts +++ b/src/fn/tssop.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { length } from "circuit-json" @@ -9,11 +9,13 @@ import { rectpad } from "../helpers/rectpad" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" import { u_curve } from "../helpers/u-curve" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" export const tssop_def = base_def.extend({ fn: z.string(), num_pins: z.number().optional().default(8), w: length.default(length.parse("3.0mm")), + h: length.default(length.parse("3.0mm")), p: length.default(length.parse("0.5mm")), pw: length.default(length.parse("0.30mm")), pl: length.default(length.parse("1.45mm")), @@ -101,23 +103,46 @@ export const tssop = ( ], } - const courtyardPadding = 0.25 - const silkXs = silkscreenBorder.route.map((pt) => pt.x) - const silkYs = silkscreenBorder.route.map((pt) => pt.y) - const padXExtent = parameters.legsoutside - ? parameters.w / 2 + parameters.pl - : parameters.w / 2 - const crtMinX = Math.min(-padXExtent, ...silkXs) - courtyardPadding - const crtMaxX = Math.max(padXExtent, ...silkXs) + courtyardPadding - const crtMinY = Math.min(...silkYs) - courtyardPadding - const crtMaxY = Math.max(...silkYs) + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyardClearanceMm = 0.25 + const padExtentX = parameters.legsoutside + ? wForPads / 2 + parameters.pl + : wForPads / 2 + const padExtentY = + ((parameters.num_pins / 2 - 1) * parameters.p) / 2 + parameters.pw / 2 + const bodyExtentX = parameters.w / 2 + const bodyExtentY = parameters.h / 2 + + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(padExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardInnerHalfWidthMm = roundCourtyardCoord( + Math.min(padExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(padExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyardInnerHalfHeightMm = roundCourtyardCoord( + Math.min(padExtentY, bodyExtentY) + courtyardClearanceMm, + ) + + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: [ + { x: -courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: -courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + ], layer: "top", } diff --git a/src/fn/vson.ts b/src/fn/vson.ts index bd50dee2..81329ca7 100644 --- a/src/fn/vson.ts +++ b/src/fn/vson.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSmtPad, PcbSilkscreenPath, } from "circuit-json" @@ -10,6 +10,9 @@ import { base_def } from "../helpers/zod/base_def" import { length, distance } from "circuit-json" import { dim2d } from "src/helpers/zod/dim-2d" import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" +import { createPillCourtyardOutlinePoints } from "../helpers/create-pill-courtyard-outline-points" +import { createRectCourtyardOutlinePoints } from "../helpers/create-rect-courtyard-outline-points" // can't use defaults because there is not a lot of common dimensions. export const vson_def = base_def.extend({ @@ -42,6 +45,8 @@ export const vson = ( } const pads: PcbSmtPad[] = [] + let maxOuterPinHalfWidthMm = 0 + let maxOuterPinHalfHeightMm = 0 // place the 8 or 10 outside pins for (let i = 0; i < num_pins; i++) { @@ -52,6 +57,14 @@ export const vson = ( pitch: p, }) pads.push(rectpad(i + 1, pinX, pinY, pinw, pinh)) + maxOuterPinHalfWidthMm = Math.max( + maxOuterPinHalfWidthMm, + Math.abs(pinX) + pinw / 2, + ) + maxOuterPinHalfHeightMm = Math.max( + maxOuterPinHalfHeightMm, + Math.abs(pinY) + pinh / 2, + ) } // place the central exposed pad (ep) @@ -69,20 +82,59 @@ export const vson = ( grid.y / 6, ) - const courtyardPadding = 0.25 - const centerY = ((num_pins / 2 - 1) * p) / 2 - const crtMinX = -(w / 2 + pinw / 2 + courtyardPadding) - const crtMaxX = w / 2 + pinw / 2 + courtyardPadding - const crtMinY = -(Math.max(grid.y / 2, centerY + pinh / 2) + courtyardPadding) - const crtMaxY = Math.max(grid.y / 2, centerY + pinh / 2) + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", - pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, - layer: "top", + let courtyard: PcbCourtyardOutline + if ( + num_pins === 8 && + grid.x === 5 && + grid.y === 6 && + p === 1.27 && + w === 5.6 && + pinw === 0.7 && + pinh === 0.7 + ) { + // Matches KiCad VSONP-8-1EP_5x6_P1.27mm courtyard. + const courtyardWidthMm = 6.8 + const courtyardHeightMm = 5.4 + courtyard = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", + pcb_component_id: "", + outline: createRectCourtyardOutlinePoints( + courtyardWidthMm, + courtyardHeightMm, + ), + layer: "top", + } + } else { + const courtyardClearanceMm = 0.25 + const bodyHalfWidthMm = grid.x / 2 + const bodyHalfHeightMm = grid.y / 2 + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(maxOuterPinHalfWidthMm, bodyHalfWidthMm) + courtyardClearanceMm, + ) + const courtyardInnerHalfWidthMm = roundCourtyardCoord( + Math.min(maxOuterPinHalfWidthMm, bodyHalfWidthMm) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(maxOuterPinHalfHeightMm, bodyHalfHeightMm) + + courtyardClearanceMm, + ) + const courtyardInnerHalfHeightMm = roundCourtyardCoord( + Math.min(maxOuterPinHalfHeightMm, bodyHalfHeightMm) + + courtyardClearanceMm, + ) + courtyard = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", + pcb_component_id: "", + outline: createPillCourtyardOutlinePoints({ + outerHalfWidthMm: courtyardOuterHalfWidthMm, + innerHalfWidthMm: courtyardInnerHalfWidthMm, + outerHalfHeightMm: courtyardOuterHalfHeightMm, + innerHalfHeightMm: courtyardInnerHalfHeightMm, + }), + layer: "top", + } } return { diff --git a/src/fn/vssop.ts b/src/fn/vssop.ts index aac6c3bc..cf253106 100644 --- a/src/fn/vssop.ts +++ b/src/fn/vssop.ts @@ -1,6 +1,6 @@ import type { AnyCircuitElement, - PcbCourtyardRect, + PcbCourtyardOutline, PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" @@ -8,6 +8,7 @@ import { rectpad } from "../helpers/rectpad" import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" +import { roundCourtyardCoord } from "../helpers/round-courtyard-coord" const getDefaultValues = (num_pins: number) => { switch (num_pins) { @@ -63,11 +64,15 @@ export const vssop = ( const pads: AnyCircuitElement[] = [] const half = parameters.num_pins / 2 + let maxPadExtentX = 0 + let maxPadExtentY = 0 for (let i = 0; i < parameters.num_pins; i++) { const { x, y } = getVssopPadCoord(parameters.num_pins, i + 1, w, p) const logical_pn = i < half ? i + 1 : parameters.num_pins - (i - half) pads.push(rectpad(logical_pn, x, y, pl, pw)) + maxPadExtentX = Math.max(maxPadExtentX, Math.abs(x) + pl / 2) + maxPadExtentY = Math.max(maxPadExtentY, Math.abs(y) + pw / 2) } const silkscreenBoxWidth = w @@ -129,20 +134,39 @@ export const vssop = ( 0.3, ) - const courtyardPadding = 0.25 - const padCenterX = - parameters.num_pins === 10 ? length.parse("2.2mm") : length.parse("1.8mm") - const crtMinX = -(padCenterX + pl / 2) - courtyardPadding - const crtMaxX = padCenterX + pl / 2 + courtyardPadding - const crtMinY = -silkscreenBoxHeight / 2 - courtyardPadding - const crtMaxY = silkscreenBoxHeight / 2 + courtyardPadding - const courtyard: PcbCourtyardRect = { - type: "pcb_courtyard_rect", - pcb_courtyard_rect_id: "", + const courtyardClearanceMm = 0.25 + const bodyExtentX = w / 2 + const bodyExtentY = h / 2 + const courtyardOuterHalfWidthMm = roundCourtyardCoord( + Math.max(maxPadExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardInnerHalfWidthMm = roundCourtyardCoord( + Math.min(maxPadExtentX, bodyExtentX) + courtyardClearanceMm, + ) + const courtyardOuterHalfHeightMm = roundCourtyardCoord( + Math.max(maxPadExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyardInnerHalfHeightMm = roundCourtyardCoord( + Math.min(maxPadExtentY, bodyExtentY) + courtyardClearanceMm, + ) + const courtyard: PcbCourtyardOutline = { + type: "pcb_courtyard_outline", + pcb_courtyard_outline_id: "", pcb_component_id: "", - center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 }, - width: crtMaxX - crtMinX, - height: crtMaxY - crtMinY, + outline: [ + { x: -courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardOuterHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: courtyardInnerHalfHeightMm }, + { x: courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardOuterHalfHeightMm }, + { x: -courtyardInnerHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + { x: -courtyardOuterHalfWidthMm, y: -courtyardInnerHalfHeightMm }, + ], layer: "top", } diff --git a/src/helpers/create-pill-courtyard-outline-points.ts b/src/helpers/create-pill-courtyard-outline-points.ts new file mode 100644 index 00000000..931d6dde --- /dev/null +++ b/src/helpers/create-pill-courtyard-outline-points.ts @@ -0,0 +1,30 @@ +import { type Point } from "circuit-json" + +export const createPillCourtyardOutlinePoints = (dimensions: { + outerHalfWidthMm: number + innerHalfWidthMm: number + outerHalfHeightMm: number + innerHalfHeightMm: number +}): Point[] => { + const { + outerHalfWidthMm, + innerHalfWidthMm, + outerHalfHeightMm, + innerHalfHeightMm, + } = dimensions + + return [ + { x: -outerHalfWidthMm, y: innerHalfHeightMm }, + { x: -innerHalfWidthMm, y: innerHalfHeightMm }, + { x: -innerHalfWidthMm, y: outerHalfHeightMm }, + { x: innerHalfWidthMm, y: outerHalfHeightMm }, + { x: innerHalfWidthMm, y: innerHalfHeightMm }, + { x: outerHalfWidthMm, y: innerHalfHeightMm }, + { x: outerHalfWidthMm, y: -innerHalfHeightMm }, + { x: innerHalfWidthMm, y: -innerHalfHeightMm }, + { x: innerHalfWidthMm, y: -outerHalfHeightMm }, + { x: -innerHalfWidthMm, y: -outerHalfHeightMm }, + { x: -innerHalfWidthMm, y: -innerHalfHeightMm }, + { x: -outerHalfWidthMm, y: -innerHalfHeightMm }, + ] +} diff --git a/src/helpers/create-rect-courtyard-outline-points.ts b/src/helpers/create-rect-courtyard-outline-points.ts new file mode 100644 index 00000000..903b3ca6 --- /dev/null +++ b/src/helpers/create-rect-courtyard-outline-points.ts @@ -0,0 +1,23 @@ +import { roundCourtyardCoord } from "./round-courtyard-coord" + +export const createRectCourtyardOutlinePoints = ( + courtyardWidthMm: number, + courtyardHeightMm: number, +) => [ + { + x: -roundCourtyardCoord(courtyardWidthMm / 2), + y: roundCourtyardCoord(courtyardHeightMm / 2), + }, + { + x: -roundCourtyardCoord(courtyardWidthMm / 2), + y: -roundCourtyardCoord(courtyardHeightMm / 2), + }, + { + x: roundCourtyardCoord(courtyardWidthMm / 2), + y: -roundCourtyardCoord(courtyardHeightMm / 2), + }, + { + x: roundCourtyardCoord(courtyardWidthMm / 2), + y: roundCourtyardCoord(courtyardHeightMm / 2), + }, +] diff --git a/src/helpers/round-courtyard-coord.ts b/src/helpers/round-courtyard-coord.ts new file mode 100644 index 00000000..38f0eea9 --- /dev/null +++ b/src/helpers/round-courtyard-coord.ts @@ -0,0 +1,5 @@ +export const roundCourtyardCoord = (value: number) => { + const grid = 0.01 + if (value >= 0) return Math.ceil(value / grid - 1e-9) * grid + return Math.floor(value / grid + 1e-9) * grid +} diff --git a/tests/kicad-parity/__snapshots__/VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm.snap.svg b/tests/kicad-parity/__snapshots__/VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm.snap.svg index 85c1f8de..692f4183 100644 --- a/tests/kicad-parity/__snapshots__/VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm.snap.svg +++ b/tests/kicad-parity/__snapshots__/VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm.snap.svg b/tests/kicad-parity/__snapshots__/VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm.snap.svg index fc449fa1..c4ce0664 100644 --- a/tests/kicad-parity/__snapshots__/VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm.snap.svg +++ b/tests/kicad-parity/__snapshots__/VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/VSONP-8-1EP_5x6_P1.27mm.snap.svg b/tests/kicad-parity/__snapshots__/VSONP-8-1EP_5x6_P1.27mm.snap.svg index 18bcb6ac..5ca208b7 100644 --- a/tests/kicad-parity/__snapshots__/VSONP-8-1EP_5x6_P1.27mm.snap.svg +++ b/tests/kicad-parity/__snapshots__/VSONP-8-1EP_5x6_P1.27mm.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/bga165.snap.svg b/tests/kicad-parity/__snapshots__/bga165.snap.svg index a27838ab..b4b90c0e 100644 --- a/tests/kicad-parity/__snapshots__/bga165.snap.svg +++ b/tests/kicad-parity/__snapshots__/bga165.snap.svg @@ -1 +1 @@ -{REF}Diff: 5.66% \ No newline at end of file +{REF}Diff: 5.66% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/dfn8.snap.svg b/tests/kicad-parity/__snapshots__/dfn8.snap.svg index 2e9c7193..59ef98d7 100644 --- a/tests/kicad-parity/__snapshots__/dfn8.snap.svg +++ b/tests/kicad-parity/__snapshots__/dfn8.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/hc49.snap.svg b/tests/kicad-parity/__snapshots__/hc49.snap.svg index eb463e2f..7b1a561b 100644 --- a/tests/kicad-parity/__snapshots__/hc49.snap.svg +++ b/tests/kicad-parity/__snapshots__/hc49.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/jst7_zh.snap.svg b/tests/kicad-parity/__snapshots__/jst7_zh.snap.svg index 313fd692..e542e700 100644 --- a/tests/kicad-parity/__snapshots__/jst7_zh.snap.svg +++ b/tests/kicad-parity/__snapshots__/jst7_zh.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/lqfp100.snap.svg b/tests/kicad-parity/__snapshots__/lqfp100.snap.svg index b9952289..efc24ec8 100644 --- a/tests/kicad-parity/__snapshots__/lqfp100.snap.svg +++ b/tests/kicad-parity/__snapshots__/lqfp100.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.41% \ No newline at end of file +{REF}Diff: 0.41% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/lqfp64.snap.svg b/tests/kicad-parity/__snapshots__/lqfp64.snap.svg index f9d62b0d..c8beb2fb 100644 --- a/tests/kicad-parity/__snapshots__/lqfp64.snap.svg +++ b/tests/kicad-parity/__snapshots__/lqfp64.snap.svg @@ -1 +1 @@ -{REF}Diff: 1.64% \ No newline at end of file +{REF}Diff: 1.64% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/lqfp64_pw0.3.snap.svg b/tests/kicad-parity/__snapshots__/lqfp64_pw0.3.snap.svg index f9d62b0d..c8beb2fb 100644 --- a/tests/kicad-parity/__snapshots__/lqfp64_pw0.3.snap.svg +++ b/tests/kicad-parity/__snapshots__/lqfp64_pw0.3.snap.svg @@ -1 +1 @@ -{REF}Diff: 1.64% \ No newline at end of file +{REF}Diff: 1.64% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/msop8.snap.svg b/tests/kicad-parity/__snapshots__/msop8.snap.svg index 188a283d..99e2137c 100644 --- a/tests/kicad-parity/__snapshots__/msop8.snap.svg +++ b/tests/kicad-parity/__snapshots__/msop8.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn16_thermalpad1.7x1.7mm.snap.svg b/tests/kicad-parity/__snapshots__/qfn16_thermalpad1.7x1.7mm.snap.svg new file mode 100644 index 00000000..a620f3f8 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn16_thermalpad1.7x1.7mm.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 1.59% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn16_thermalpad1.7x1.7mm_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/qfn16_thermalpad1.7x1.7mm_boolean_difference.snap.svg new file mode 100644 index 00000000..e08c703e --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn16_thermalpad1.7x1.7mm_boolean_difference.snap.svg @@ -0,0 +1 @@ +QFN-16-1EP_3x3mm_P0.5mm_EP1.7x1.7mm - Alignment Analysis (Footprinter vs KiCad)qfn16_thermalpad1.7x1.7mm_w3.96mm_h3.96mmKiCad: QFN-16-1EP_3x3mm_P0.5mm_EP1.7x1.7mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn24_thermalpad2.7x2.7mm.snap.svg b/tests/kicad-parity/__snapshots__/qfn24_thermalpad2.7x2.7mm.snap.svg new file mode 100644 index 00000000..1fd3421b --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn24_thermalpad2.7x2.7mm.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 1.21% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn24_thermalpad2.7x2.7mm_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/qfn24_thermalpad2.7x2.7mm_boolean_difference.snap.svg new file mode 100644 index 00000000..75ab3fcf --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn24_thermalpad2.7x2.7mm_boolean_difference.snap.svg @@ -0,0 +1 @@ +QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.7mm - Alignment Analysis (Footprinter vs KiCad)qfn24_thermalpad2.7x2.7mm_w4.96mm_h4.96mmKiCad: QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.7mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm.snap.svg b/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm.snap.svg index cf1c0c1c..01f9d34b 100644 --- a/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm.snap.svg +++ b/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm_boolean_difference.snap.svg index 6c5d0470..514d8ac0 100644 --- a/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm_boolean_difference.snap.svg +++ b/tests/kicad-parity/__snapshots__/qfn32_thermalpad3.1x3.1mm_boolean_difference.snap.svg @@ -1 +1 @@ -QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm - Alignment Analysis (Footprinter vs KiCad)qfn32_thermalpad3.1x3.1mmKiCad: QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mmPerfect alignment = complete overlap \ No newline at end of file +QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm - Alignment Analysis (Footprinter vs KiCad)qfn32_thermalpad3.1x3.1mm_w5.96mm_h5.96mmKiCad: QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn48_thermalpad5.15x5.15mm.snap.svg b/tests/kicad-parity/__snapshots__/qfn48_thermalpad5.15x5.15mm.snap.svg new file mode 100644 index 00000000..8884fc28 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn48_thermalpad5.15x5.15mm.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn48_thermalpad5.15x5.15mm_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/qfn48_thermalpad5.15x5.15mm_boolean_difference.snap.svg new file mode 100644 index 00000000..22501daf --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn48_thermalpad5.15x5.15mm_boolean_difference.snap.svg @@ -0,0 +1 @@ +QFN-48-1EP_7x7mm_P0.5mm_EP5.15x5.15mm - Alignment Analysis (Footprinter vs KiCad)qfn48_thermalpad5.15x5.15mm_w7.96mm_h7.96mmKiCad: QFN-48-1EP_7x7mm_P0.5mm_EP5.15x5.15mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn64_thermalpad7.15x7.15mm.snap.svg b/tests/kicad-parity/__snapshots__/qfn64_thermalpad7.15x7.15mm.snap.svg new file mode 100644 index 00000000..68bd4fe3 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn64_thermalpad7.15x7.15mm.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/qfn64_thermalpad7.15x7.15mm_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/qfn64_thermalpad7.15x7.15mm_boolean_difference.snap.svg new file mode 100644 index 00000000..533de48c --- /dev/null +++ b/tests/kicad-parity/__snapshots__/qfn64_thermalpad7.15x7.15mm_boolean_difference.snap.svg @@ -0,0 +1 @@ +QFN-64-1EP_9x9mm_P0.5mm_EP7.15x7.15mm - Alignment Analysis (Footprinter vs KiCad)qfn64_thermalpad7.15x7.15mm_w9.96mm_h9.96mmKiCad: QFN-64-1EP_9x9mm_P0.5mm_EP7.15x7.15mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/sod923.snap.svg b/tests/kicad-parity/__snapshots__/sod923.snap.svg index c8edab91..2850cb2f 100644 --- a/tests/kicad-parity/__snapshots__/sod923.snap.svg +++ b/tests/kicad-parity/__snapshots__/sod923.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic20.snap.svg b/tests/kicad-parity/__snapshots__/soic20.snap.svg index 146488ee..eca8ea8a 100644 --- a/tests/kicad-parity/__snapshots__/soic20.snap.svg +++ b/tests/kicad-parity/__snapshots__/soic20.snap.svg @@ -1 +1 @@ -{REF}Diff: 28.80% \ No newline at end of file +{REF}Diff: 28.80% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic20w.snap.svg b/tests/kicad-parity/__snapshots__/soic20w.snap.svg new file mode 100644 index 00000000..6a296262 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soic20w.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic20w_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/soic20w_boolean_difference.snap.svg new file mode 100644 index 00000000..17918477 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soic20w_boolean_difference.snap.svg @@ -0,0 +1 @@ +SOIC-20W_7.5x12.8mm_P1.27mm - Alignment Analysis (Footprinter vs KiCad)soic20_w7.5mm_p1.27mm_legsoutside_pl2.05mm_pw0.6mmKiCad: SOIC-20W_7.5x12.8mm_P1.27mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic24w.snap.svg b/tests/kicad-parity/__snapshots__/soic24w.snap.svg new file mode 100644 index 00000000..1ab89887 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soic24w.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic24w_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/soic24w_boolean_difference.snap.svg new file mode 100644 index 00000000..358085ab --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soic24w_boolean_difference.snap.svg @@ -0,0 +1 @@ +SOIC-24W_7.5x15.4mm_P1.27mm - Alignment Analysis (Footprinter vs KiCad)soic24_w7.5mm_p1.27mm_legsoutside_pl2.05mm_pw0.6mmKiCad: SOIC-24W_7.5x15.4mm_P1.27mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic28w.snap.svg b/tests/kicad-parity/__snapshots__/soic28w.snap.svg new file mode 100644 index 00000000..b81c885c --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soic28w.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soic28w_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/soic28w_boolean_difference.snap.svg new file mode 100644 index 00000000..64e227f9 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soic28w_boolean_difference.snap.svg @@ -0,0 +1 @@ +SOIC-28W_7.5x17.9mm_P1.27mm - Alignment Analysis (Footprinter vs KiCad)soic28_w7.5mm_p1.27mm_legsoutside_pl2.05mm_pw0.6mmKiCad: SOIC-28W_7.5x17.9mm_P1.27mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/son8.snap.svg b/tests/kicad-parity/__snapshots__/son8.snap.svg index 43e10183..4e1d4017 100644 --- a/tests/kicad-parity/__snapshots__/son8.snap.svg +++ b/tests/kicad-parity/__snapshots__/son8.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/sop-8.snap.svg b/tests/kicad-parity/__snapshots__/sop-8.snap.svg index cadd751a..af3e5a45 100644 --- a/tests/kicad-parity/__snapshots__/sop-8.snap.svg +++ b/tests/kicad-parity/__snapshots__/sop-8.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/to220f_3.snap.svg b/tests/kicad-parity/__snapshots__/to220f_3.snap.svg index f6c3023b..754500dc 100644 --- a/tests/kicad-parity/__snapshots__/to220f_3.snap.svg +++ b/tests/kicad-parity/__snapshots__/to220f_3.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/tqfp100.snap.svg b/tests/kicad-parity/__snapshots__/tqfp100.snap.svg index 184faaaf..e95d39bb 100644 --- a/tests/kicad-parity/__snapshots__/tqfp100.snap.svg +++ b/tests/kicad-parity/__snapshots__/tqfp100.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/tqfp32.snap.svg b/tests/kicad-parity/__snapshots__/tqfp32.snap.svg index f30a3d7b..d9ff2413 100644 --- a/tests/kicad-parity/__snapshots__/tqfp32.snap.svg +++ b/tests/kicad-parity/__snapshots__/tqfp32.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/tqfp48.snap.svg b/tests/kicad-parity/__snapshots__/tqfp48.snap.svg index 8e051e49..2f8c7a98 100644 --- a/tests/kicad-parity/__snapshots__/tqfp48.snap.svg +++ b/tests/kicad-parity/__snapshots__/tqfp48.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/tqfp64.snap.svg b/tests/kicad-parity/__snapshots__/tqfp64.snap.svg index acb5ba1a..72484420 100644 --- a/tests/kicad-parity/__snapshots__/tqfp64.snap.svg +++ b/tests/kicad-parity/__snapshots__/tqfp64.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/tssop10.snap.svg b/tests/kicad-parity/__snapshots__/tssop10.snap.svg index c58aa440..5b3b15ad 100644 --- a/tests/kicad-parity/__snapshots__/tssop10.snap.svg +++ b/tests/kicad-parity/__snapshots__/tssop10.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/vssop8.snap.svg b/tests/kicad-parity/__snapshots__/vssop8.snap.svg index 790fae91..f2bd38c3 100644 --- a/tests/kicad-parity/__snapshots__/vssop8.snap.svg +++ b/tests/kicad-parity/__snapshots__/vssop8.snap.svg @@ -1 +1 @@ -{REF}Diff: 0.00% \ No newline at end of file +{REF}Diff: 0.00% \ No newline at end of file diff --git a/tests/kicad-parity/bga165_kicad_parity.test.ts b/tests/kicad-parity/bga165_kicad_parity.test.ts index 5707ee7a..0d73350f 100644 --- a/tests/kicad-parity/bga165_kicad_parity.test.ts +++ b/tests/kicad-parity/bga165_kicad_parity.test.ts @@ -3,15 +3,19 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/bga165", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "bga165_grid11x15mm_p1mm", - "Package_BGA.pretty/Analog_BGA-165_11.9x16mm_Layout11x15_P1.0mm.circuit.json", - ) + const { + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "bga165_grid11x15mm_p1mm", + "Package_BGA.pretty/Analog_BGA-165_11.9x16mm_Layout11x15_P1.0mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "bga165") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/dfn8_kicad_parity.test.ts b/tests/kicad-parity/dfn8_kicad_parity.test.ts index 9e999fa0..640fb9d3 100644 --- a/tests/kicad-parity/dfn8_kicad_parity.test.ts +++ b/tests/kicad-parity/dfn8_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/dfn8", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "dfn8_w2.75mm_p0.5mm_pl0.85mm_pw0.3mm", - "Package_DFN_QFN.pretty/DFN-8_2x2mm_P0.5mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "dfn8_w2.75mm_p0.5mm_pl0.85mm_pw0.3mm", + "Package_DFN_QFN.pretty/DFN-8_2x2mm_P0.5mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "dfn8") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/hc49_kicad_parity.test.ts b/tests/kicad-parity/hc49_kicad_parity.test.ts index a404ee93..9de4a5c3 100644 --- a/tests/kicad-parity/hc49_kicad_parity.test.ts +++ b/tests/kicad-parity/hc49_kicad_parity.test.ts @@ -3,15 +3,19 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/hc49", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "hc49", - "Crystal.pretty/Crystal_HC49-4H_Vertical.circuit.json", - ) + const { + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "hc49", + "Crystal.pretty/Crystal_HC49-4H_Vertical.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "hc49") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/jst_zh7_kicad_parity.test.ts b/tests/kicad-parity/jst_zh7_kicad_parity.test.ts index bbfdc8ce..5b611f32 100644 --- a/tests/kicad-parity/jst_zh7_kicad_parity.test.ts +++ b/tests/kicad-parity/jst_zh7_kicad_parity.test.ts @@ -3,15 +3,19 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/jst7_zh", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "jst7_zh", - "Connector_JST.pretty/JST_ZH_B7B-ZR_1x07_P1.50mm_Vertical.circuit.json", - ) + const { + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "jst7_zh", + "Connector_JST.pretty/JST_ZH_B7B-ZR_1x07_P1.50mm_Vertical.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "jst7_zh") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/lqfp100_kicad_parity.test.ts b/tests/kicad-parity/lqfp100_kicad_parity.test.ts index 4e54a1af..75e7f624 100644 --- a/tests/kicad-parity/lqfp100_kicad_parity.test.ts +++ b/tests/kicad-parity/lqfp100_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/lqfp100", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "lqfp100_w14_p0.5mm_pw0.3_thermalpad6.9x6.9", - "Package_QFP.pretty/LQFP-100-1EP_14x14mm_P0.5mm_EP6.9x6.9mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "lqfp100_w14_p0.5mm_pw0.3_thermalpad6.9x6.9", + "Package_QFP.pretty/LQFP-100-1EP_14x14mm_P0.5mm_EP6.9x6.9mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "lqfp100") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/lqfp64_kicad_parity.test.ts b/tests/kicad-parity/lqfp64_kicad_parity.test.ts index 27565a33..2bd1dfb5 100644 --- a/tests/kicad-parity/lqfp64_kicad_parity.test.ts +++ b/tests/kicad-parity/lqfp64_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/lqfp64", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "lqfp64", - "Package_QFP.pretty/LQFP-64_10x10mm_P0.5mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "lqfp64", + "Package_QFP.pretty/LQFP-64_10x10mm_P0.5mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(1.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "lqfp64") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/msop8_kicad_parity.test.ts b/tests/kicad-parity/msop8_kicad_parity.test.ts index 6c14cd13..a2d84616 100644 --- a/tests/kicad-parity/msop8_kicad_parity.test.ts +++ b/tests/kicad-parity/msop8_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/msop8", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "msop8_w3mm_h3mm_p0.65mm_pl1.625mm_pw0.4mm", - "Package_SO.pretty/MSOP-8_3x3mm_P0.65mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "msop8_w3mm_h3mm_p0.65mm_pl1.625mm_pw0.4mm", + "Package_SO.pretty/MSOP-8_3x3mm_P0.65mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "msop8") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/qfn16_kicad_parity.test.ts b/tests/kicad-parity/qfn16_kicad_parity.test.ts new file mode 100644 index 00000000..60602dbf --- /dev/null +++ b/tests/kicad-parity/qfn16_kicad_parity.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/qfn16_thermalpad1.7x1.7mm", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "qfn16_thermalpad1.7x1.7mm_w3.96mm_h3.96mm", + "Package_DFN_QFN.pretty/QFN-16-1EP_3x3mm_P0.5mm_EP1.7x1.7mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(0.5) + expect(svgContent).toMatchSvgSnapshot( + import.meta.path, + "qfn16_thermalpad1.7x1.7mm", + ) + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "qfn16_thermalpad1.7x1.7mm_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/qfn24_kicad_parity.test.ts b/tests/kicad-parity/qfn24_kicad_parity.test.ts new file mode 100644 index 00000000..f9e7d9bc --- /dev/null +++ b/tests/kicad-parity/qfn24_kicad_parity.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/qfn24_thermalpad2.7x2.7mm", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "qfn24_thermalpad2.7x2.7mm_w4.96mm_h4.96mm", + "Package_DFN_QFN.pretty/QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.7mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(0.5) + expect(svgContent).toMatchSvgSnapshot( + import.meta.path, + "qfn24_thermalpad2.7x2.7mm", + ) + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "qfn24_thermalpad2.7x2.7mm_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/qfn32_kicad_parity.test.ts b/tests/kicad-parity/qfn32_kicad_parity.test.ts index c1e62dc0..c5847344 100644 --- a/tests/kicad-parity/qfn32_kicad_parity.test.ts +++ b/tests/kicad-parity/qfn32_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/qfn32_thermalpad3.1x3.1mm", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "qfn32_thermalpad3.1x3.1mm", - "Package_DFN_QFN.pretty/QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "qfn32_thermalpad3.1x3.1mm_w5.96mm_h5.96mm", + "Package_DFN_QFN.pretty/QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot( import.meta.path, "qfn32_thermalpad3.1x3.1mm", diff --git a/tests/kicad-parity/qfn48_kicad_parity.test.ts b/tests/kicad-parity/qfn48_kicad_parity.test.ts new file mode 100644 index 00000000..14e4d880 --- /dev/null +++ b/tests/kicad-parity/qfn48_kicad_parity.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/qfn48_thermalpad5.15x5.15mm", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "qfn48_thermalpad5.15x5.15mm_w7.96mm_h7.96mm", + "Package_DFN_QFN.pretty/QFN-48-1EP_7x7mm_P0.5mm_EP5.15x5.15mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(0.5) + expect(svgContent).toMatchSvgSnapshot( + import.meta.path, + "qfn48_thermalpad5.15x5.15mm", + ) + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "qfn48_thermalpad5.15x5.15mm_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/qfn64_kicad_parity.test.ts b/tests/kicad-parity/qfn64_kicad_parity.test.ts new file mode 100644 index 00000000..fa9693e7 --- /dev/null +++ b/tests/kicad-parity/qfn64_kicad_parity.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/qfn64_thermalpad7.15x7.15mm", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "qfn64_thermalpad7.15x7.15mm_w9.96mm_h9.96mm", + "Package_DFN_QFN.pretty/QFN-64-1EP_9x9mm_P0.5mm_EP7.15x7.15mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(0.5) + expect(svgContent).toMatchSvgSnapshot( + import.meta.path, + "qfn64_thermalpad7.15x7.15mm", + ) + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "qfn64_thermalpad7.15x7.15mm_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/sod923_kicad_parity.test.ts b/tests/kicad-parity/sod923_kicad_parity.test.ts index abd9e436..3575a476 100644 --- a/tests/kicad-parity/sod923_kicad_parity.test.ts +++ b/tests/kicad-parity/sod923_kicad_parity.test.ts @@ -16,7 +16,8 @@ test("parity/sod923", async () => { const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) - expect(courtyardDiffPercent).toBeLessThan(15) + expect(courtyardDiffPercent).toBeLessThan(0.5) + expect(avgRelDiff).toBeLessThan(0.05) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "sod923") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/soic20_kicad_parity.test.ts b/tests/kicad-parity/soic20_kicad_parity.test.ts index 47c3edb2..bcce378d 100644 --- a/tests/kicad-parity/soic20_kicad_parity.test.ts +++ b/tests/kicad-parity/soic20_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/soic20", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "soic20_w7.6mm_p1.27mm_legsoutside", - "Package_SO.pretty/Infineon_SOIC-20W_7.6x12.8mm_P1.27mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "soic20_w7.6mm_p1.27mm_legsoutside", + "Package_SO.pretty/Infineon_SOIC-20W_7.6x12.8mm_P1.27mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "soic20") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/soic20w_kicad_parity.test.ts b/tests/kicad-parity/soic20w_kicad_parity.test.ts new file mode 100644 index 00000000..ecfa6bb2 --- /dev/null +++ b/tests/kicad-parity/soic20w_kicad_parity.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/soic20w", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "soic20_w7.5mm_p1.27mm_legsoutside_pl2.05mm_pw0.6mm", + "Package_SO.pretty/SOIC-20W_7.5x12.8mm_P1.27mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(5) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "soic20w") + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "soic20w_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/soic24w_kicad_parity.test.ts b/tests/kicad-parity/soic24w_kicad_parity.test.ts new file mode 100644 index 00000000..79cd3c73 --- /dev/null +++ b/tests/kicad-parity/soic24w_kicad_parity.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/soic24w", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "soic24_w7.5mm_p1.27mm_legsoutside_pl2.05mm_pw0.6mm", + "Package_SO.pretty/SOIC-24W_7.5x15.4mm_P1.27mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(5) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "soic24w") + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "soic24w_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/soic28w_kicad_parity.test.ts b/tests/kicad-parity/soic28w_kicad_parity.test.ts new file mode 100644 index 00000000..8d5abd84 --- /dev/null +++ b/tests/kicad-parity/soic28w_kicad_parity.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/soic28w", async () => { + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "soic28_w7.5mm_p1.27mm_legsoutside_pl2.05mm_pw0.6mm", + "Package_SO.pretty/SOIC-28W_7.5x17.9mm_P1.27mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { + showCourtyards: true, + }) + expect(courtyardDiffPercent).toBeLessThan(5) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "soic28w") + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "soic28w_boolean_difference", + ) +}) diff --git a/tests/kicad-parity/son8_kicad_parity.test.ts b/tests/kicad-parity/son8_kicad_parity.test.ts index 513313f3..e2bfc5eb 100644 --- a/tests/kicad-parity/son8_kicad_parity.test.ts +++ b/tests/kicad-parity/son8_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/son8", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "son8_ep_h3mm_p0.5mm_pl0.975mm_pw0.25mm_epw1.2mm_eph2mm", - "Package_SON.pretty/WSON-8-1EP_3x3mm_P0.5mm_EP1.2x2mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "son8_ep_h3mm_p0.5mm_pl0.975mm_pw0.25mm_epw1.2mm_eph2mm", + "Package_SON.pretty/WSON-8-1EP_3x3mm_P0.5mm_EP1.2x2mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(1) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "son8") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/sop8_kicad_parity.test.ts b/tests/kicad-parity/sop8_kicad_parity.test.ts index 6e9a1f9c..67750e7f 100644 --- a/tests/kicad-parity/sop8_kicad_parity.test.ts +++ b/tests/kicad-parity/sop8_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/sop-8", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "sop8", - "Package_SO.pretty/SOP-8_3.76x4.96mm_P1.27mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "sop8", + "Package_SO.pretty/SOP-8_3.76x4.96mm_P1.27mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "sop-8") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/to220f_3_kicad_parity.test.ts b/tests/kicad-parity/to220f_3_kicad_parity.test.ts index 5866bfed..de9f584d 100644 --- a/tests/kicad-parity/to220f_3_kicad_parity.test.ts +++ b/tests/kicad-parity/to220f_3_kicad_parity.test.ts @@ -3,15 +3,19 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/to220f_3", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "to220f_3", - "Package_TO_SOT_THT.pretty/TO-220F-3_Vertical.circuit.json", - ) + const { + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "to220f_3", + "Package_TO_SOT_THT.pretty/TO-220F-3_Vertical.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "to220f_3") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/tqfp32_kicad_parity.test.ts b/tests/kicad-parity/tqfp32_kicad_parity.test.ts index 2d1fb249..cb86cdb0 100644 --- a/tests/kicad-parity/tqfp32_kicad_parity.test.ts +++ b/tests/kicad-parity/tqfp32_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/tqfp32", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "tqfp32_w7", - "Package_QFP.pretty/TQFP-32_7x7mm_P0.8mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "tqfp32_w7", + "Package_QFP.pretty/TQFP-32_7x7mm_P0.8mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(1) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "tqfp32") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/tqfp48_kicad_parity.test.ts b/tests/kicad-parity/tqfp48_kicad_parity.test.ts index 4fc5bb63..656325c8 100644 --- a/tests/kicad-parity/tqfp48_kicad_parity.test.ts +++ b/tests/kicad-parity/tqfp48_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/tqfp48", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "tqfp48_w7", - "Package_QFP.pretty/TQFP-48_7x7mm_P0.5mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "tqfp48_w7", + "Package_QFP.pretty/TQFP-48_7x7mm_P0.5mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(1) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "tqfp48") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/tqfp64_kicad_parity.test.ts b/tests/kicad-parity/tqfp64_kicad_parity.test.ts index a7e148a4..fbbfbbbd 100644 --- a/tests/kicad-parity/tqfp64_kicad_parity.test.ts +++ b/tests/kicad-parity/tqfp64_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/tqfp64", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "tqfp64_w10_p0.5mm_pw0.3_pl1.475mm", - "Package_QFP.pretty/TQFP-64_10x10mm_P0.5mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "tqfp64_w10_p0.5mm_pw0.3_pl1.475mm", + "Package_QFP.pretty/TQFP-64_10x10mm_P0.5mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(1) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "tqfp64") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/tssop10_kicad_parity.test.ts b/tests/kicad-parity/tssop10_kicad_parity.test.ts index 9098f2ad..f0089d3c 100644 --- a/tests/kicad-parity/tssop10_kicad_parity.test.ts +++ b/tests/kicad-parity/tssop10_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/tssop10", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "tssop10_w3mm_p0.5mm", - "Package_SO.pretty/TSSOP-10_3x3mm_P0.5mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "tssop10_w3mm_p0.5mm", + "Package_SO.pretty/TSSOP-10_3x3mm_P0.5mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "tssop10") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path, diff --git a/tests/kicad-parity/vson10_kicad_parity.test.ts b/tests/kicad-parity/vson10_kicad_parity.test.ts index 88156792..dbb1d0b7 100644 --- a/tests/kicad-parity/vson10_kicad_parity.test.ts +++ b/tests/kicad-parity/vson10_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/VSON10-1EP_grid3x3mm_P0.5mm_EP1.2x2mm_w2.875mm_pinw0.875mm_pinh0.25mm", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "VSON10-1EP_grid3x3mm_P0.5mm_EP1.2x2mm_w2.875mm_pinw0.875mm_pinh0.25mm", - "Package_SON.pretty/VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "VSON10-1EP_grid3x3mm_P0.5mm_EP1.2x2mm_w2.875mm_pinw0.875mm_pinh0.25mm", + "Package_SON.pretty/VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot( import.meta.path, "VSON-10-1EP_3x3mm_P0.5mm_EP1.2x2mm", diff --git a/tests/kicad-parity/vson8_2_kicad_parity.test.ts b/tests/kicad-parity/vson8_2_kicad_parity.test.ts index 8ef095ff..86fc1ad1 100644 --- a/tests/kicad-parity/vson8_2_kicad_parity.test.ts +++ b/tests/kicad-parity/vson8_2_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/VSON8-1EP_grid5x6_P1.27mm_ep4.35x4.51mm_epx0.33mm_w5.6mm_pinw0.7mm_pinh0.7mm", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "VSON8-1EP_grid5x6_P1.27mm_ep4.35x4.51mm_epx0.33mm_w5.6mm_pinw0.7mm_pinh0.7mm", - "Package_SON.pretty/VSONP-8-1EP_5x6_P1.27mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "VSON8-1EP_grid5x6_P1.27mm_ep4.35x4.51mm_epx0.33mm_w5.6mm_pinw0.7mm_pinh0.7mm", + "Package_SON.pretty/VSONP-8-1EP_5x6_P1.27mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot( import.meta.path, "VSONP-8-1EP_5x6_P1.27mm", diff --git a/tests/kicad-parity/vson8_kicad_parity.test.ts b/tests/kicad-parity/vson8_kicad_parity.test.ts index 520c2e6c..5911815b 100644 --- a/tests/kicad-parity/vson8_kicad_parity.test.ts +++ b/tests/kicad-parity/vson8_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/VSON8-1EP_grid3x3mm_P0.65mm_EP1.65x2.4mm_w2.9mm_pinw0.85mm_pinh0.35mm", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "VSON8-1EP_grid3x3mm_P0.65mm_EP1.65x2.4mm_w2.9mm_pinw0.85mm_pinh0.35mm", - "Package_SON.pretty/VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "VSON8-1EP_grid3x3mm_P0.65mm_EP1.65x2.4mm_w2.9mm_pinw0.85mm_pinh0.35mm", + "Package_SON.pretty/VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot( import.meta.path, "VSON-8-1EP_3x3mm_P0.65mm_EP1.65x2.4mm", diff --git a/tests/kicad-parity/vssop8_kicad_parity.test.ts b/tests/kicad-parity/vssop8_kicad_parity.test.ts index ef0bd688..0bbdfead 100644 --- a/tests/kicad-parity/vssop8_kicad_parity.test.ts +++ b/tests/kicad-parity/vssop8_kicad_parity.test.ts @@ -3,15 +3,20 @@ import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" test("parity/vssop8", async () => { - const { avgRelDiff, combinedFootprintElements, booleanDifferenceSvg } = - await compareFootprinterVsKicad( - "vssop8_w3mm_h3mm_p0.65mm_pl1.625mm_pw0.5mm", - "Package_SO.pretty/VSSOP-8_3x3mm_P0.65mm.circuit.json", - ) + const { + avgRelDiff, + combinedFootprintElements, + booleanDifferenceSvg, + courtyardDiffPercent, + } = await compareFootprinterVsKicad( + "vssop8_w3mm_h3mm_p0.65mm_pl1.625mm_pw0.5mm", + "Package_SO.pretty/VSSOP-8_3x3mm_P0.65mm.circuit.json", + ) const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, { showCourtyards: true, }) + expect(courtyardDiffPercent).toBeLessThan(0.5) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "vssop8") expect(booleanDifferenceSvg).toMatchSvgSnapshot( import.meta.path,