Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { inflateSourceChip } from "./inflators/inflateSourceChip"
import { inflateSourceCapacitor } from "./inflators/inflateSourceCapacitor"
import { inflateSourceInductor } from "./inflators/inflateSourceInductor"
import { inflateSourceDiode } from "./inflators/inflateSourceDiode"
import { inflateSourceTrace } from "./inflators/inflateSourceTrace"

export class Subcircuit extends Group<typeof subcircuitProps> {
constructor(props: z.input<typeof subcircuitProps>) {
Expand Down Expand Up @@ -83,10 +84,14 @@ export class Subcircuit extends Group<typeof subcircuitProps> {
}
}

// Finally, inflate source ports (group ports)
const sourcePorts = injectionDb.source_port.list()
for (const sourcePort of sourcePorts) {
inflateSourcePort(sourcePort, inflationCtx)
}

const sourceTraces = injectionDb.source_trace.list()
for (const sourceTrace of sourceTraces) {
inflateSourceTrace(sourceTrace, inflationCtx)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { SourceTrace } from "circuit-json"
import { Trace } from "lib/components/primitive-components/Trace/Trace"
import type { InflatorContext } from "../InflatorFn"
import type { CircuitJsonUtilObjects } from "@tscircuit/circuit-json-util"

const getSelectorPath = (
component: { name: string; source_group_id: string | undefined },
db: CircuitJsonUtilObjects,
): string => {
const path_parts: string[] = []
let currentGroupId = component.source_group_id
while (currentGroupId) {
const group = db.source_group.get(currentGroupId)
if (!group) break
path_parts.unshift(`.${group.name}`)
currentGroupId = group.parent_source_group_id
}
path_parts.push(`.${component.name}`)
return path_parts.join(" > ")
}

export function inflateSourceTrace(
sourceTrace: SourceTrace,
inflatorContext: InflatorContext,
) {
const { injectionDb, subcircuit } = inflatorContext

const connectedSelectors: string[] = []

// Get selectors for connected ports
for (const sourcePortId of sourceTrace.connected_source_port_ids) {
const sourcePort = injectionDb.source_port.get(sourcePortId)
if (!sourcePort) continue

let selector: string | undefined
if (sourcePort.source_component_id) {
const sourceComponent = injectionDb.source_component.get(
sourcePort.source_component_id,
)
if (sourceComponent) {
// This is a port on a component, e.g. .G1 > .R1 > .pin1
const path = getSelectorPath(
{
name: sourceComponent.name,
source_group_id: sourceComponent.source_group_id,
},
injectionDb,
)
selector = `${path} > .${sourcePort.name}`
}
} else {
// This is a port on a group, usually the root group of the subcircuit.
// e.g. .P1
selector = `.${sourcePort.name}`
}

if (selector) {
connectedSelectors.push(selector)
}
}

// Get selectors for connected nets
for (const sourceNetId of sourceTrace.connected_source_net_ids) {
const sourceNet = injectionDb.source_net.get(sourceNetId)
if (sourceNet) {
connectedSelectors.push(`net.${sourceNet.name}`)
}
}

if (connectedSelectors.length < 2) return

const trace = new Trace({
path: connectedSelectors,
})

// Set source_trace_id on the new trace
trace.source_trace_id = sourceTrace.source_trace_id

subcircuit.add(trace)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { test, expect } from "bun:test"
import { getTestFixture } from "tests/fixtures/get-test-fixture"
import { renderToCircuitJson } from "tests/fixtures/renderToCircuitJson"

test("subcircuit-circuit-json06 - trace inflation", async () => {
const { circuit } = await getTestFixture()

const subcircuitCircuitJson = await renderToCircuitJson(
<group name="G1">
<resistor name="R1" resistance="10k" footprint="0402" />
<resistor name="R2" resistance="1k" footprint="0402" />
<trace from=".R1 > .pin2" to=".R2 > .pin1" />
</group>,
)

circuit.add(
<board width="20mm" height="20mm">
<subcircuit name="S1" circuitJson={subcircuitCircuitJson} pcbX={-5} />
<resistor name="R3" resistance="1k" footprint="0402" pcbX={5} />
</board>,
)

await circuit.renderUntilSettled()

const circuitJson = await circuit.getCircuitJson()

// Find the trace between R1 and R2 inside the subcircuit
const sourceTraces = circuitJson.filter((elm) => elm.type === "source_trace")

const sourceTraceR1R2 = sourceTraces.find((elm: any) => {
if (!elm.connected_source_port_ids) return false
const connectedPorts = elm.connected_source_port_ids
.map((id: string) => {
const port = circuitJson.find(
(p: any) => p.type === "source_port" && p.source_port_id === id,
) as any
if (!port) return null
const comp = circuitJson.find(
(c: any) =>
c.type === "source_component" &&
c.source_component_id === port.source_component_id,
) as any
if (!comp) return null
return `${comp.name}.${port.name}`
})
.filter(Boolean)

return (
connectedPorts.includes("R1.pin2") && connectedPorts.includes("R2.pin1")
)
})

expect(sourceTraceR1R2).toBeDefined()

const pcbTraces = circuitJson.filter((c) => c.type === "pcb_trace")
const pcbTraceR1R2 = pcbTraces.find(
(c: any) => c.source_trace_id === (sourceTraceR1R2 as any).source_trace_id,
)

expect(pcbTraceR1R2).toBeDefined()

expect(pcbTraces).toHaveLength(1)

expect(circuit).toMatchPcbSnapshot(import.meta.path)
})