Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { PcbComponent } from "circuit-json"
import { Footprint } from "lib/components/primitive-components/Footprint"
import { extractPcbPrimitivesFromCircuitJson } from "lib/utils/extractPcbPrimitivesFromCircuitJson"
import type { InflatorContext } from "../InflatorFn"
import { inflatePcbComponentPrimitives } from "./inflatePcbComponentPrimitives"

/**
* Inflates a Footprint component from circuit JSON by extracting all PCB primitives
Expand All @@ -14,20 +13,11 @@ import type { InflatorContext } from "../InflatorFn"
export const inflateFootprintComponent = (
pcbElm: PcbComponent,
inflatorContext: InflatorContext,
): Footprint | null => {
const { injectionDb, normalComponent } = inflatorContext
) => {
const { normalComponent } = inflatorContext
if (!normalComponent) return null

const primitives = extractPcbPrimitivesFromCircuitJson({
pcbComponent: pcbElm,
db: injectionDb,
return inflatePcbComponentPrimitives(pcbElm, {
componentName: normalComponent.name,
inflatorContext,
})

if (primitives.length === 0) return null

const footprint = new Footprint({ originalLayer: pcbElm.layer })
footprint.addAll(primitives)

return footprint
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { PcbComponent } from "circuit-json"
import { Footprint } from "lib/components/primitive-components/Footprint"
import { extractPcbPrimitivesFromCircuitJson } from "lib/utils/extractPcbPrimitivesFromCircuitJson"
import type { InflatorContext } from "../InflatorFn"

export const inflatePcbComponentPrimitives = (
pcbComponent: PcbComponent,
{
componentName,
inflatorContext,
}: {
componentName: string
inflatorContext: InflatorContext
},
): Footprint | null => {
const primitives = extractPcbPrimitivesFromCircuitJson({
pcbComponent,
db: inflatorContext.injectionDb,
componentName,
})

if (primitives.length === 0) return null

const footprint = new Footprint({ originalLayer: pcbComponent.layer })
footprint.addAll(primitives)

return footprint
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { PcbComponent, SourceSimpleFiducial } from "circuit-json"
import { ImportedPcbComponent } from "lib/components/primitive-components/ImportedPcbComponent"
import type { InflatorContext } from "../InflatorFn"
import { inflatePcbComponentPrimitives } from "./inflatePcbComponentPrimitives"
import { getInflatedPcbPlacement } from "./getInflatedPcbPlacement"

export function inflateSourceFiducial(
sourceElm: SourceSimpleFiducial,
inflatorContext: InflatorContext,
) {
const { injectionDb, subcircuit, groupsMap } = inflatorContext

const pcbElm = injectionDb.pcb_component.getWhere({
source_component_id: sourceElm.source_component_id,
}) as PcbComponent | null

const { pcbX, pcbY } = getInflatedPcbPlacement({
pcbComponent: pcbElm,
sourceGroupId: sourceElm.source_group_id,
inflatorContext,
})

const fiducial = new ImportedPcbComponent({
height: pcbElm?.height,
name: sourceElm.name,
layer: pcbElm?.layer,
obstructsWithinBounds: pcbElm?.obstructs_within_bounds,
pcbX,
pcbY,
pcbRotation: pcbElm?.rotation,
doNotPlace: pcbElm?.do_not_place,
width: pcbElm?.width,
})

if (pcbElm) {
const footprint = inflatePcbComponentPrimitives(pcbElm, {
componentName: sourceElm.name,
inflatorContext,
})

if (footprint) {
fiducial.add(footprint)
}
}

if (sourceElm.source_group_id && groupsMap?.has(sourceElm.source_group_id)) {
const group = groupsMap.get(sourceElm.source_group_id)!
group.add(fiducial)
} else {
subcircuit.add(fiducial)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { CadComponent, PcbComponent, SourceSimpleLed } from "circuit-json"
import { Led } from "lib/components/normal-components/Led"
import type { InflatorContext } from "../InflatorFn"
import { inflateFootprintComponent } from "./inflateFootprintComponent"
import { getInflatedPcbPlacement } from "./getInflatedPcbPlacement"

export function inflateSourceLed(
sourceElm: SourceSimpleLed,
inflatorContext: InflatorContext,
) {
const { injectionDb, subcircuit, groupsMap } = inflatorContext

const pcbElm = injectionDb.pcb_component.getWhere({
source_component_id: sourceElm.source_component_id,
}) as PcbComponent | null

const cadElm = injectionDb.cad_component.getWhere({
source_component_id: sourceElm.source_component_id,
}) as CadComponent | null

const { pcbX, pcbY } = getInflatedPcbPlacement({
pcbComponent: pcbElm,
sourceGroupId: sourceElm.source_group_id,
inflatorContext,
})

const led = new Led({
name: sourceElm.name,
color: sourceElm.color,
wavelength: sourceElm.wavelength,
layer: pcbElm?.layer,
pcbX,
pcbY,
pcbRotation: pcbElm?.rotation,
doNotPlace: pcbElm?.do_not_place,
obstructsWithinBounds: pcbElm?.obstructs_within_bounds,
})

if (pcbElm) {
const footprint = inflateFootprintComponent(pcbElm, {
...inflatorContext,
normalComponent: led,
})

if (footprint) {
led.add(footprint)
}
}

if (sourceElm.source_group_id && groupsMap?.has(sourceElm.source_group_id)) {
const group = groupsMap.get(sourceElm.source_group_id)!
group.add(led)
} else {
subcircuit.add(led)
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import type {
LayerRef,
PcbTrace,
PcbTraceRoutePoint,
SourceTrace,
} from "circuit-json"
import type { PcbTrace, PcbVia, SourceTrace } from "circuit-json"
import { Trace } from "lib/components/primitive-components/Trace/Trace"
import {
type ManualPcbPathPoint,
pcbTraceRouteToPcbPath,
} from "lib/utils/pcbTraceRouteToPcbPath"
import { setImportedTracePayload } from "lib/components/primitive-components/Trace/imported-trace-payload-registry"
import type { InflatorContext } from "../InflatorFn"

const getSelectorPath = (
Expand Down Expand Up @@ -90,28 +82,37 @@ export function inflateSourceTrace(
return
}

const pcbTrace = injectionDb.pcb_trace.getWhere({
source_trace_id: sourceTrace.source_trace_id,
})

let pcbPath: ManualPcbPathPoint[] | undefined
if (pcbTrace) {
pcbPath = pcbTraceRouteToPcbPath(pcbTrace.route)
}

// Extract trace width from source_trace or pcb_trace route points
const pcbTraces = injectionDb.pcb_trace
.list()
.filter(
(pcbTrace) => pcbTrace.source_trace_id === sourceTrace.source_trace_id,
)

const inflatedPcbVias: PcbVia[] | undefined =
pcbTraces.length > 0
? injectionDb.pcb_via
.list()
.filter((via) =>
pcbTraces.some(
(pcbTrace) => pcbTrace.pcb_trace_id === via.pcb_trace_id,
),
)
: undefined

// Extract trace width from source_trace or the first imported pcb_trace route
let traceWidth: number | undefined = sourceTrace.min_trace_thickness
if (!traceWidth && pcbTrace?.route) {
// Try to get width from the first wire point in the route
const wirePoint = pcbTrace.route.find((pt) => pt.route_type === "wire")
if (wirePoint && wirePoint.route_type === "wire") {
traceWidth = wirePoint.width
if (!traceWidth) {
for (const pcbTrace of pcbTraces) {
const wirePoint = pcbTrace.route.find((pt) => pt.route_type === "wire")
if (wirePoint && wirePoint.route_type === "wire") {
traceWidth = wirePoint.width
break
}
}
}

const traceProps: {
path: string[]
pcbPath?: ManualPcbPathPoint[]
pcbStraightLine?: boolean
thickness?: number
} = {
Expand All @@ -122,12 +123,8 @@ export function inflateSourceTrace(
traceProps.thickness = traceWidth
}

// If pcbPath has intermediate points, use manual routing
// Otherwise, use straight-line routing (simple 2-point traces)
if (pcbPath && pcbPath.length > 0) {
traceProps.pcbPath = pcbPath
} else if (
!pcbTrace &&
if (
pcbTraces.length === 0 &&
sourceTrace.connected_source_port_ids.length === 2 &&
sourceTrace.connected_source_net_ids.length === 0
) {
Expand All @@ -137,12 +134,11 @@ export function inflateSourceTrace(
}

const trace = new Trace(traceProps)
trace._inflatedPcbTrace = pcbTrace ?? undefined
trace._inflatedPcbVias = pcbTrace
? injectionDb.pcb_via
.list()
.filter((via) => via.pcb_trace_id === pcbTrace.pcb_trace_id)
: undefined
setImportedTracePayload(trace, {
importedPcbTraces: pcbTraces.length > 0 ? pcbTraces : undefined,
importedPcbVias: inflatedPcbVias,
importedSourceTrace: sourceTrace,
})

subcircuit.add(trace)
}
65 changes: 65 additions & 0 deletions lib/components/primitive-components/ImportedPcbComponent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { LayerRef } from "circuit-json"
import { z } from "zod"
import { PrimitiveComponent } from "../base-components/PrimitiveComponent"

const importedPcbComponentProps = z.object({
doNotPlace: z.boolean().optional(),
height: z.number().optional(),
layer: z.custom<LayerRef>().optional(),
name: z.string().optional(),
obstructsWithinBounds: z.boolean().optional(),
pcbRotation: z.number().optional(),
pcbX: z.number().optional(),
pcbY: z.number().optional(),
width: z.number().optional(),
})

export class ImportedPcbComponent extends PrimitiveComponent<
typeof importedPcbComponentProps
> {
isPrimitiveContainer = true

get config() {
return {
componentName: "ImportedPcbComponent",
sourceFtype: "simple_fiducial" as const,
zodProps: importedPcbComponentProps,
}
}

protected _getPcbComponentLayer(): LayerRef | undefined {
return this._parsedProps.layer
}

doInitialSourceRender() {
const { db } = this.root!
const sourceComponent = db.source_component.insert({
ftype: "simple_fiducial",
name: this.name,
})

this.source_component_id = sourceComponent.source_component_id
}

doInitialPcbComponentRender() {
if (this.root?.pcbDisabled) return
const { db } = this.root!
const { _parsedProps: props } = this
const { pcbX = 0, pcbY = 0 } = this.getResolvedPcbPositionProp()

const pcbComponent = db.pcb_component.insert({
center: { x: pcbX, y: pcbY },
width: props.width ?? 0,
height: props.height ?? 0,
layer: props.layer ?? "top",
rotation: props.pcbRotation ?? 0,
source_component_id: this.source_component_id!,
subcircuit_id: this.getSubcircuit().subcircuit_id ?? undefined,
pcb_group_id: this.getGroup()?.pcb_group_id ?? undefined,
do_not_place: props.doNotPlace ?? false,
obstructs_within_bounds: props.obstructsWithinBounds ?? true,
})

this.pcb_component_id = pcbComponent.pcb_component_id
}
}
Loading
Loading