Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getBoundsOfPcbElements #15

Merged
merged 3 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/npm-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
run: bun install

- name: Run tests
run: bun test
run: bun run test
Binary file modified bun.lockb
Binary file not shown.
293 changes: 293 additions & 0 deletions docs/CIRCUIT_JSON_PCB_ELEMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
# Circuit JSON Specification: PCB Component Overview

> Created at 2024-09-20T18:37:19.158Z
> Latest Version: https://github.com/tscircuit/circuit-json/blob/main/docs/PCB_COMPONENT_OVERVIEW.md

Any type below can be imported from `circuit-json`. Every type has a corresponding
snake_case version which is a zod type that can be used to parse unknown json,
for example `PcbComponent` has a `pcb_component.parse` function that you
can also import.

```ts
export interface PcbFabricationNotePath {
type: "pcb_fabrication_note_path"
pcb_fabrication_note_path_id: string
pcb_component_id: string
layer: LayerRef
route: Point[]
stroke_width: Length
color?: string
}

export interface PcbComponent {
type: "pcb_component"
pcb_component_id: string
source_component_id: string
center: Point
layer: LayerRef
rotation: Rotation
width: Length
height: Length
}

export interface PcbPortNotMatchedError {
type: "pcb_port_not_matched_error"
pcb_error_id: string
message: string
pcb_component_ids: string[]
}

export interface PcbSilkscreenText {
type: "pcb_silkscreen_text"
pcb_silkscreen_text_id: string
font: "tscircuit2024"
font_size: Length
pcb_component_id: string
text: string
layer: LayerRef
anchor_position: Point
anchor_alignment:
| "center"
| "top_left"
| "top_right"
| "bottom_left"
| "bottom_right"
}

export interface PcbSilkscreenPill {
type: "pcb_silkscreen_pill"
pcb_silkscreen_pill_id: string
pcb_component_id: string
center: Point
width: Length
height: Length
layer: LayerRef
}

export interface PcbPlatedHoleCircle {
type: "pcb_plated_hole"
shape: "circle"
outer_diameter: number
hole_diameter: number
x: Distance
y: Distance
layers: LayerRef[]
port_hints?: string[]
pcb_component_id?: string
pcb_port_id?: string
pcb_plated_hole_id: string
}

export interface PcbPlatedHoleOval {
type: "pcb_plated_hole"
shape: "oval" | "pill"
outer_width: number
outer_height: number
hole_width: number
hole_height: number
x: Distance
y: Distance
layers: LayerRef[]
port_hints?: string[]
pcb_component_id?: string
pcb_port_id?: string
pcb_plated_hole_id: string
}

export type PcbPlatedHole = PcbPlatedHoleCircle | PcbPlatedHoleOval

export interface PcbFabricationNoteText {
type: "pcb_fabrication_note_text"
pcb_fabrication_note_text_id: string
font: "tscircuit2024"
font_size: Length
pcb_component_id: string
text: string
layer: VisibleLayer
anchor_position: Point
anchor_alignment:
| "center"
| "top_left"
| "top_right"
| "bottom_left"
| "bottom_right"
color?: string
}

export interface PcbSilkscreenCircle {
type: "pcb_silkscreen_circle"
pcb_silkscreen_circle_id: string
pcb_component_id: string
center: Point
radius: Length
layer: VisibleLayer
}

export interface PcbSilkscreenPath {
type: "pcb_silkscreen_path"
pcb_silkscreen_path_id: string
pcb_component_id: string
layer: VisibleLayerRef
route: Point[]
stroke_width: Length
}

export interface PcbText {
type: "pcb_text"
pcb_text_id: string
text: string
center: Point
layer: LayerRef
width: Length
height: Length
lines: number
align: "bottom-left"
}

export type PCBKeepout = z.infer<typeof pcb_keepout>

export interface PcbVia {
type: "pcb_via"
pcb_via_id: string
x: Distance
y: Distance
outer_diameter: Distance
hole_diameter: Distance
layers: LayerRef[]
}

export interface PcbSilkscreenOval {
type: "pcb_silkscreen_oval"
pcb_silkscreen_oval_id: string
pcb_component_id: string
center: Point
radius_x: Distance
radius_y: Distance
layer: VisibleLayer
}

export interface PcbPlacementError {
type: "pcb_placement_error"
pcb_placement_error_id: string
message: string
}

export interface PcbPort {
type: "pcb_port"
pcb_port_id: string
source_port_id: string
pcb_component_id: string
x: Distance
y: Distance
layers: LayerRef[]
}

export interface PcbTraceHint {
type: "pcb_trace_hint"
pcb_trace_hint_id: string
pcb_port_id: string
pcb_component_id: string
route: RouteHintPoint[]
}

export interface PcbSmtPadCircle {
type: "pcb_smtpad"
shape: "circle"
pcb_smtpad_id: string
x: Distance
y: Distance
radius: number
layer: LayerRef
port_hints?: string[]
pcb_component_id?: string
pcb_port_id?: string
}

export interface PcbSmtPadRect {
type: "pcb_smtpad"
shape: "rect"
pcb_smtpad_id: string
x: Distance
y: Distance
width: number
height: number
layer: LayerRef
port_hints?: string[]
pcb_component_id?: string
pcb_port_id?: string
}

export type PcbSmtPad = PcbSmtPadCircle | PcbSmtPadRect

export interface PcbSilkscreenLine {
type: "pcb_silkscreen_line"
pcb_silkscreen_line_id: string
pcb_component_id: string
stroke_width: Distance
x1: Distance
y1: Distance
x2: Distance
y2: Distance
layer: VisibleLayer
}

export interface PcbHoleCircleOrSquare {
type: "pcb_hole"
pcb_hole_id: string
hole_shape: "circle" | "square"
hole_diameter: number
x: Distance
y: Distance
}

export interface PcbHoleOval {
type: "pcb_hole"
pcb_hole_id: string
hole_shape: "oval"
hole_width: number
hole_height: number
x: Distance
y: Distance
}

export type PcbHole = PcbHoleCircleOrSquare | PcbHoleOval

export interface PcbTraceRoutePointWire {
route_type: "wire"
x: Distance
y: Distance
width: Distance
start_pcb_port_id?: string
end_pcb_port_id?: string
layer: LayerRef
}

export interface PcbTraceRoutePointVia {
route_type: "via"
x: Distance
y: Distance
from_layer: string
to_layer: string
}

export type PcbTraceRoutePoint = PcbTraceRoutePointWire | PcbTraceRoutePointVia

export interface PcbTrace {
type: "pcb_trace"
source_trace_id?: string
pcb_component_id?: string
pcb_trace_id: string
route_thickness_mode?: "constant" | "interpolated"
should_round_corners?: boolean
route: Array<PcbTraceRoutePoint>
}

export interface PcbBoard {
type: "pcb_board"
pcb_board_id: string
width: Length
height: Length
center: Point
outline?: Point[]
}
```
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export * from "./lib/apply-selector"
export * from "./lib/get-element-by-id"
export * from "./lib/get-element-id"
export * from "./lib/readable-name-functions/get-readable-name-for-element"
export * from "./lib/get-bounds-of-pcb-elements"

export { default as su } from "./lib/su"
42 changes: 42 additions & 0 deletions lib/get-bounds-of-pcb-elements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { AnyCircuitElement } from "@tscircuit/soup"

export const getBoundsOfPcbElements = (
elements: AnyCircuitElement[],
): { minX: number; minY: number; maxX: number; maxY: number } => {
let minX = Number.POSITIVE_INFINITY
let minY = Number.POSITIVE_INFINITY
let maxX = Number.NEGATIVE_INFINITY
let maxY = Number.NEGATIVE_INFINITY

for (const elm of elements) {
if (!elm.type.startsWith("pcb_")) continue
if ("x" in elm && "y" in elm) {
minX = Math.min(minX, elm.x)
minY = Math.min(minY, elm.y)
maxX = Math.max(maxX, elm.x)
maxY = Math.max(maxY, elm.y)

if ("width" in elm) {
maxX = Math.max(maxX, elm.x + elm.width)
}
if ("height" in elm) {
maxY = Math.max(maxY, elm.y + elm.height)
}
if ("radius" in elm) {
minX = Math.min(minX, elm.x - elm.radius)
minY = Math.min(minY, elm.y - elm.radius)
maxX = Math.max(maxX, elm.x + elm.radius)
maxY = Math.max(maxY, elm.y + elm.radius)
}
} else if (elm.type === "pcb_trace") {
for (const point of elm.route) {
minX = Math.min(minX, point.x)
minY = Math.min(minY, point.y)
maxX = Math.max(maxX, point.x)
maxY = Math.max(maxY, point.y)
}
}
}

return { minX, minY, maxX, maxY }
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
"zod": "*"
},
"devDependencies": {
"@biomejs/biome": "^1.9.2",
"@tscircuit/soup": "^0.0.71",
"transformation-matrix": "^2.16.1",
"ava": "^6.1.2",
"esbuild": "^0.20.2",
"esbuild-register": "^3.5.0",
"transformation-matrix": "^2.16.1",
"tsup": "^8.0.2",
"typescript": "^5.4.5",
"zod": "^3.23.6"
Expand Down
Loading
Loading