add support for pcb cutouts#14
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
| if (cutout.shape === "rect") { | ||
| const pcbX = cutout.center.x | ||
| const pcbY = cutout.center.y | ||
| const width = mmStr(cutout.width) | ||
| const height = mmStr(cutout.height) | ||
| const rotation = cutout.rotation !== undefined ? ` pcbRotation="${mmStr(cutout.rotation)}"` : "" | ||
|
|
||
| elementStrings.push( | ||
| `<pcbcutout shape="rect" pcbX="${mmStr(pcbX)}" pcbY="${mmStr(pcbY)}" width="${width}" height="${height}"${rotation} />`, |
There was a problem hiding this comment.
Emit rotation in millimeters instead of degrees
Rectangular cutouts format pcbRotation with mmStr, producing values such as pcbRotation="45mm". Rotation is an angular quantity, so appending mm makes the attribute nonsensical and will cause any consumer that expects degrees to misinterpret or ignore the rotation. Use the raw angle (or a degree helper) rather than a millimeter string.
Useful? React with 👍 / 👎.
| test("test pcb_cutout conversion - all shapes", async () => { | ||
| const circuitJson: AnyCircuitElement[] = [ | ||
| { | ||
| type: "pcb_cutout", | ||
| pcb_cutout_id: "cutout1", | ||
| shape: "rect", | ||
| center: { x: 0, y: 0 }, | ||
| width: 5, | ||
| height: 3, | ||
| rotation: 45, | ||
| }, | ||
| { | ||
| type: "pcb_cutout", | ||
| pcb_cutout_id: "cutout2", | ||
| shape: "circle", | ||
| center: { x: 10, y: 10 }, | ||
| radius: 2.5, | ||
| }, | ||
| { | ||
| type: "pcb_cutout", | ||
| pcb_cutout_id: "cutout3", | ||
| shape: "polygon", | ||
| points: [ | ||
| { x: 0, y: 0 }, | ||
| { x: 5, y: 0 }, | ||
| { x: 5, y: 5 }, | ||
| { x: 0, y: 5 }, | ||
| ], | ||
| }, | ||
| ] | ||
|
|
||
| const tscircuit = convertCircuitJsonToTscircuit(circuitJson, { | ||
| componentName: "ComponentWithCutouts", | ||
| }) | ||
|
|
||
| expect(tscircuit).toMatchInlineSnapshot(` | ||
| "import { type ChipProps } from "tscircuit" | ||
| export const ComponentWithCutouts = (props: ChipProps) => ( | ||
| <chip | ||
| footprint={<footprint> | ||
| <pcbcutout shape="rect" pcbX="0mm" pcbY="0mm" width="5mm" height="3mm" pcbRotation="45mm" /> | ||
| <pcbcutout shape="circle" pcbX="10mm" pcbY="10mm" radius="2.5mm" /> | ||
| <pcbcutout shape="polygon" points={[{"x":0,"y":0},{"x":5,"y":0},{"x":5,"y":5},{"x":0,"y":5}]} /> | ||
| </footprint>} | ||
| {...props} | ||
| /> | ||
| )" | ||
| `) | ||
| }) | ||
|
|
||
| test("test pcb_cutout conversion - rect without rotation", async () => { | ||
| const circuitJson: AnyCircuitElement[] = [ | ||
| { | ||
| type: "pcb_cutout", | ||
| pcb_cutout_id: "cutout1", | ||
| shape: "rect", | ||
| center: { x: 2, y: 3 }, | ||
| width: 10, | ||
| height: 5, | ||
| }, | ||
| ] | ||
|
|
||
| const tscircuit = convertCircuitJsonToTscircuit(circuitJson, { | ||
| componentName: "ComponentWithRectCutout", | ||
| }) | ||
|
|
||
| expect(tscircuit).toMatchInlineSnapshot(` | ||
| "import { type ChipProps } from "tscircuit" | ||
| export const ComponentWithRectCutout = (props: ChipProps) => ( | ||
| <chip | ||
| footprint={<footprint> | ||
| <pcbcutout shape="rect" pcbX="2mm" pcbY="3mm" width="10mm" height="5mm" /> | ||
| </footprint>} | ||
| {...props} | ||
| /> | ||
| )" | ||
| `) | ||
| }) | ||
|
|
||
| test("test pcb_cutout conversion - mixed with other elements", async () => { | ||
| const circuitJson: AnyCircuitElement[] = [ | ||
| { | ||
| type: "pcb_smtpad", | ||
| pcb_smtpad_id: "pad1", | ||
| shape: "rect", | ||
| x: 0, | ||
| y: 0, | ||
| width: 1, | ||
| height: 1, | ||
| layer: "top", | ||
| port_hints: ["1"], | ||
| }, | ||
| { | ||
| type: "pcb_cutout", | ||
| pcb_cutout_id: "cutout1", | ||
| shape: "circle", | ||
| center: { x: 5, y: 5 }, | ||
| radius: 1.5, | ||
| }, | ||
| { | ||
| type: "pcb_hole", | ||
| pcb_hole_id: "hole1", | ||
| hole_shape: "circle", | ||
| x: 10, | ||
| y: 10, | ||
| hole_diameter: 0.5, | ||
| }, | ||
| ] | ||
|
|
||
| const tscircuit = convertCircuitJsonToTscircuit(circuitJson, { | ||
| componentName: "ComponentWithMixedElements", | ||
| }) | ||
|
|
||
| expect(tscircuit).toMatchInlineSnapshot(` | ||
| "import { type ChipProps } from "tscircuit" | ||
| export const ComponentWithMixedElements = (props: ChipProps) => ( | ||
| <chip | ||
| footprint={<footprint> | ||
| <hole pcbX="10mm" pcbY="10mm" diameter="0.5mm" /> | ||
| <smtpad portHints={["1"]} pcbX="0mm" pcbY="0mm" width="1mm" height="1mm" shape="rect" /> | ||
| <pcbcutout shape="circle" pcbX="5mm" pcbY="5mm" radius="1.5mm" /> | ||
| </footprint>} | ||
| {...props} | ||
| /> | ||
| )" | ||
| `) | ||
| }) |
There was a problem hiding this comment.
This test file violates the project rule limiting *.test.ts files to at most one test() function. The file contains three test functions (lines 11, 61, and 90) and must be split into separate numbered files: test5-pcb-cutout1.test.tsx, test5-pcb-cutout2.test.tsx, and test5-pcb-cutout3.test.tsx, with each file containing only one test function.
Spotted by Graphite Agent (based on custom rule: Custom rule)
Is this helpful? React 👍 or 👎 to let us know.
No description provided.