diff --git a/.gitignore b/.gitignore index c323f1d..a2e71c9 100644 --- a/.gitignore +++ b/.gitignore @@ -186,3 +186,6 @@ static-server .yalc yalc.lock .vercel +*.diff.png + +test.json \ No newline at end of file diff --git a/algos/infinite-grid-ijump-astar/tests/__snapshots__/multilayer-trace.snap.svg b/algos/infinite-grid-ijump-astar/tests/__snapshots__/multilayer-trace.snap.svg new file mode 100644 index 0000000..2b10fb7 --- /dev/null +++ b/algos/infinite-grid-ijump-astar/tests/__snapshots__/multilayer-trace.snap.svg @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/algos/infinite-grid-ijump-astar/tests/multilayer-trace.test.ts b/algos/infinite-grid-ijump-astar/tests/multilayer-trace.test.ts new file mode 100644 index 0000000..d2b1315 --- /dev/null +++ b/algos/infinite-grid-ijump-astar/tests/multilayer-trace.test.ts @@ -0,0 +1,356 @@ +import { getSimpleRouteJson } from "autorouting-dataset" +import { test, expect } from "bun:test" +import { circuitJsonToPcbSvg } from "circuit-to-svg" +import { IJumpAutorouter } from "../v2" + +const soup: any = [ + { + type: "source_port", + source_port_id: "source_port_0", + name: "pin1", + pin_number: 1, + port_hints: ["-", "left", "pin1", "1"], + source_component_id: "source_component_0", + }, + { + type: "source_port", + source_port_id: "source_port_1", + name: "pin2", + pin_number: 2, + port_hints: ["+", "right", "pin2", "2"], + source_component_id: "source_component_0", + }, + { + type: "source_component", + source_component_id: "source_component_0", + ftype: "simple_resistor", + name: "R1", + resistance: 10000, + }, + { + type: "source_port", + source_port_id: "source_port_2", + name: "pin1", + pin_number: 1, + port_hints: ["-", "left", "pin1", "1"], + source_component_id: "source_component_1", + }, + { + type: "source_port", + source_port_id: "source_port_3", + name: "pin2", + pin_number: 2, + port_hints: ["+", "right", "pin2", "2"], + source_component_id: "source_component_1", + }, + { + type: "source_component", + source_component_id: "source_component_1", + ftype: "simple_resistor", + name: "R2", + resistance: 10000, + }, + { + type: "source_port", + source_port_id: "source_port_4", + name: "pin1", + pin_number: 1, + port_hints: ["-", "left", "pin1", "1"], + source_component_id: "source_component_2", + }, + { + type: "source_port", + source_port_id: "source_port_5", + name: "pin2", + pin_number: 2, + port_hints: ["+", "right", "pin2", "2"], + source_component_id: "source_component_2", + }, + { + type: "source_component", + source_component_id: "source_component_2", + ftype: "simple_resistor", + name: "R_obstacle", + resistance: 10000, + }, + { + type: "source_trace", + source_trace_id: "source_trace_0", + connected_source_port_ids: ["source_port_1", "source_port_2"], + connected_source_net_ids: [], + }, + { + type: "schematic_component", + schematic_component_id: "schematic_component_0", + center: { x: 0, y: 0 }, + rotation: 0, + size: { width: 1, height: 0.55 }, + source_component_id: "source_component_0", + symbol_name: "boxresistor_horz", + }, + { + type: "schematic_component", + schematic_component_id: "schematic_component_1", + center: { x: 0, y: 0 }, + rotation: 0, + size: { width: 1, height: 0.55 }, + source_component_id: "source_component_1", + symbol_name: "boxresistor_horz", + }, + { + type: "schematic_component", + schematic_component_id: "schematic_component_2", + center: { x: 0, y: 0 }, + rotation: 0, + size: { width: 1, height: 0.55 }, + source_component_id: "source_component_2", + symbol_name: "boxresistor_horz", + }, + { + type: "schematic_port", + schematic_port_id: "schematic_port_0", + schematic_component_id: "schematic_component_0", + center: { x: -0.5, y: 0 }, + source_port_id: "source_port_0", + facing_direction: "left", + }, + { + type: "schematic_port", + schematic_port_id: "schematic_port_1", + schematic_component_id: "schematic_component_0", + center: { x: 0.5, y: 0 }, + source_port_id: "source_port_1", + facing_direction: "right", + }, + { + type: "schematic_port", + schematic_port_id: "schematic_port_2", + schematic_component_id: "schematic_component_1", + center: { x: -0.5, y: 0 }, + source_port_id: "source_port_2", + facing_direction: "left", + }, + { + type: "schematic_port", + schematic_port_id: "schematic_port_3", + schematic_component_id: "schematic_component_1", + center: { x: 0.5, y: 0 }, + source_port_id: "source_port_3", + facing_direction: "right", + }, + { + type: "schematic_port", + schematic_port_id: "schematic_port_4", + schematic_component_id: "schematic_component_2", + center: { x: -0.5, y: 0 }, + source_port_id: "source_port_4", + facing_direction: "left", + }, + { + type: "schematic_port", + schematic_port_id: "schematic_port_5", + schematic_component_id: "schematic_component_2", + center: { x: 0.5, y: 0 }, + source_port_id: "source_port_5", + facing_direction: "right", + }, + { + type: "pcb_component", + pcb_component_id: "pcb_component_0", + center: { x: -5, y: 0 }, + width: 1.5999999999999996, + height: 0.6000000000000001, + layer: "top", + rotation: 0, + source_component_id: "source_component_0", + }, + { + type: "pcb_component", + pcb_component_id: "pcb_component_1", + center: { x: 5, y: 0 }, + width: 1.5999999999999996, + height: 0.6000000000000001, + layer: "top", + rotation: 0, + source_component_id: "source_component_1", + }, + { + type: "pcb_component", + pcb_component_id: "pcb_component_2", + center: { x: 0, y: 0 }, + width: 4.3, + height: 1.5, + layer: "top", + rotation: 0, + source_component_id: "source_component_2", + }, + { + type: "pcb_board", + pcb_board_id: "pcb_board_0", + center: { x: 0, y: 0 }, + width: 12, + height: 10, + }, + { + type: "pcb_smtpad", + pcb_smtpad_id: "pcb_smtpad_0", + pcb_component_id: "pcb_component_0", + pcb_port_id: "pcb_port_0", + layer: "bottom", + shape: "rect", + width: 0.6000000000000001, + height: 0.6000000000000001, + port_hints: ["1", "left"], + x: -5.5, + y: 0, + }, + { + type: "pcb_smtpad", + pcb_smtpad_id: "pcb_smtpad_1", + pcb_component_id: "pcb_component_0", + pcb_port_id: "pcb_port_1", + layer: "bottom", + shape: "rect", + width: 0.6000000000000001, + height: 0.6000000000000001, + port_hints: ["2", "right"], + x: -4.5, + y: 0, + }, + { + type: "pcb_smtpad", + pcb_smtpad_id: "pcb_smtpad_2", + pcb_component_id: "pcb_component_1", + pcb_port_id: "pcb_port_2", + layer: "bottom", + shape: "rect", + width: 0.6000000000000001, + height: 0.6000000000000001, + port_hints: ["1", "left"], + x: 4.5, + y: 0, + }, + { + type: "pcb_smtpad", + pcb_smtpad_id: "pcb_smtpad_3", + pcb_component_id: "pcb_component_1", + pcb_port_id: "pcb_port_3", + layer: "bottom", + shape: "rect", + width: 0.6000000000000001, + height: 0.6000000000000001, + port_hints: ["2", "right"], + x: 5.5, + y: 0, + }, + { + type: "pcb_smtpad", + pcb_smtpad_id: "pcb_smtpad_4", + pcb_component_id: "pcb_component_2", + pcb_port_id: "pcb_port_4", + layer: "top", + shape: "rect", + width: 1.5, + height: 1.5, + port_hints: ["1", "left"], + x: -1.4, + y: 0, + }, + { + type: "pcb_smtpad", + pcb_smtpad_id: "pcb_smtpad_5", + pcb_component_id: "pcb_component_2", + pcb_port_id: "pcb_port_5", + layer: "top", + shape: "rect", + width: 1.5, + height: 1.5, + port_hints: ["2", "right"], + x: 1.4, + y: 0, + }, + { + type: "pcb_port", + pcb_port_id: "pcb_port_0", + pcb_component_id: "pcb_component_0", + layers: ["bottom"], + x: -5.5, + y: 0, + source_port_id: "source_port_0", + }, + { + type: "pcb_port", + pcb_port_id: "pcb_port_1", + pcb_component_id: "pcb_component_0", + layers: ["bottom"], + x: -4.5, + y: 0, + source_port_id: "source_port_1", + }, + { + type: "pcb_port", + pcb_port_id: "pcb_port_2", + pcb_component_id: "pcb_component_1", + layers: ["bottom"], + x: 4.5, + y: 0, + source_port_id: "source_port_2", + }, + { + type: "pcb_port", + pcb_port_id: "pcb_port_3", + pcb_component_id: "pcb_component_1", + layers: ["bottom"], + x: 5.5, + y: 0, + source_port_id: "source_port_3", + }, + { + type: "pcb_port", + pcb_port_id: "pcb_port_4", + pcb_component_id: "pcb_component_2", + layers: ["top"], + x: -1.4, + y: 0, + source_port_id: "source_port_4", + }, + { + type: "pcb_port", + pcb_port_id: "pcb_port_5", + pcb_component_id: "pcb_component_2", + layers: ["top"], + x: 1.4, + y: 0, + source_port_id: "source_port_5", + }, + { + type: "pcb_trace_hint", + pcb_trace_hint_id: "pcb_trace_hint_0", + pcb_component_id: null, + pcb_port_id: "pcb_port_1", + route: [{ x: -3, y: 0, via: true }], + }, + { + type: "pcb_trace_hint", + pcb_trace_hint_id: "pcb_trace_hint_1", + pcb_component_id: null, + pcb_port_id: "pcb_port_2", + route: [{ x: 3, y: 0, via: true }], + }, +] + +test("ijump-astar: multilayer trace", () => { + const input = getSimpleRouteJson(soup) + + const autorouter = new IJumpAutorouter({ + input, + }) + + const traces = autorouter.solveAndMapToTraces() + + Bun.write("test.json", JSON.stringify(soup.concat(traces))) + + expect(circuitJsonToPcbSvg(soup.concat(traces))).toMatchSvgSnapshot( + import.meta.path, + ) +}) diff --git a/algos/infinite-grid-ijump-astar/v1/lib/getObstaclesFromTrace.ts b/algos/infinite-grid-ijump-astar/v1/lib/getObstaclesFromTrace.ts index c212394..5075ddf 100644 --- a/algos/infinite-grid-ijump-astar/v1/lib/getObstaclesFromTrace.ts +++ b/algos/infinite-grid-ijump-astar/v1/lib/getObstaclesFromTrace.ts @@ -22,6 +22,7 @@ export const getObstaclesFromTrace = ( const obstacle: Obstacle = { type: "rect", + layers: [start.layer], center: { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2, diff --git a/algos/infinite-grid-ijump-astar/v2/lib/GeneralizedAstar.ts b/algos/infinite-grid-ijump-astar/v2/lib/GeneralizedAstar.ts index 12083eb..1cbdbad 100644 --- a/algos/infinite-grid-ijump-astar/v2/lib/GeneralizedAstar.ts +++ b/algos/infinite-grid-ijump-astar/v2/lib/GeneralizedAstar.ts @@ -15,9 +15,13 @@ import { ObstacleList } from "./ObstacleList" const debug = Debug("autorouting-dataset:astar") +export interface PointWithLayer extends Point { + layer: string +} + export type ConnectionSolveResult = | { solved: false; connectionName: string } - | { solved: true; connectionName: string; route: Point[] } + | { solved: true; connectionName: string; route: PointWithLayer[] } export class GeneralizedAstarAutorouter { openSet: Node[] = [] @@ -185,10 +189,15 @@ export class GeneralizedAstarAutorouter { const { solved, current } = this.solveOneStep() if (solved) { - const route: Point[] = [] + const route: PointWithLayer[] = [] let node: Node | null = current while (node) { - route.unshift({ x: node.x, y: node.y }) + route.unshift({ + x: node.x, + y: node.y, + // TODO: this layer should be included as part of the node + layer: pointsToConnect[0].layer, + }) node = node.parent } @@ -221,10 +230,15 @@ export class GeneralizedAstarAutorouter { const obstaclesFromTraces: Obstacle[] = [] this.debugTraceCount = 0 for (const connection of this.input.connections) { + const dominantLayer = connection.pointsToConnect[0].layer ?? "top" this.debugTraceCount += 1 this.obstacles = new ObstacleList( this.allObstacles .filter((obstacle) => !obstacle.connectedTo.includes(connection.name)) + // TODO obstacles on different layers should be filtered inside + // the algorithm, not for the entire connection, this is a hack in + // relation to https://github.com/tscircuit/tscircuit/issues/432 + .filter((obstacle) => obstacle.layers.includes(dominantLayer)) .concat(obstaclesFromTraces), ) const result = this.solveConnection(connection) @@ -237,7 +251,14 @@ export class GeneralizedAstarAutorouter { if (result.solved) { solutions.push(result) obstaclesFromTraces.push( - ...getObstaclesFromRoute(result.route, connection.name), + ...getObstaclesFromRoute( + result.route.map((p) => ({ + x: p.x, + y: p.y, + layer: dominantLayer, + })), + connection.name, + ), ) } } @@ -259,7 +280,7 @@ export class GeneralizedAstarAutorouter { x: point.x, y: point.y, width: 0.1, // TODO use configurable width - layer: "top", // Default layer, adjust as needed + layer: point.layer, })), }, ] diff --git a/bun.lockb b/bun.lockb index 735de2d..7a58d1f 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..b13c929 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[test] +preload = ["./module/tests/fixtures/preload.ts"] \ No newline at end of file diff --git a/module/lib/generators/index.ts b/module/lib/generators/index.ts index 5e1ddd0..c5adeee 100644 --- a/module/lib/generators/index.ts +++ b/module/lib/generators/index.ts @@ -1,5 +1,6 @@ import { getDistantSingleTraceProblemGenerator } from "./distant-single-trace" import { getSingleTraceProblemGenerator } from "./single-trace" +import { getSingleTraceMultilayerProblemGenerator } from "./single-trace-multilayer" import { getTracesProblemGenerator } from "./traces" import type { ProblemGenerator, ProblemType } from "./types" @@ -12,6 +13,8 @@ export const getDatasetGenerator = ( return getTracesProblemGenerator() } else if (problemType === "distant-single-trace") { return getDistantSingleTraceProblemGenerator() + } else if (problemType === "single-trace-multilayer") { + return getSingleTraceMultilayerProblemGenerator() } throw new Error( `Generator for "${problemType}" not found, may not be implemented`, diff --git a/module/lib/generators/single-trace-multilayer/SingleTraceMultilayerCircuit.tsx b/module/lib/generators/single-trace-multilayer/SingleTraceMultilayerCircuit.tsx new file mode 100644 index 0000000..777aa2b --- /dev/null +++ b/module/lib/generators/single-trace-multilayer/SingleTraceMultilayerCircuit.tsx @@ -0,0 +1,65 @@ +import { getRandomFootprint } from "../../generator-utils/getRandomFootprint" +import { rand } from "../../generator-utils/rand" + +export type SingleTrace2FootprintsProps = { + seed: number + distance?: number +} + +const seed1Footprint = { + footprint: "0402", + pinCount: 2, + footprintType: "passive", +} + +export const SingleTrace2Footprints = ({ + seed, + distance = 10, +}: SingleTrace2FootprintsProps) => { + const rotation = rand(seed, "rotation").range(0, Math.PI * 2) + const aFoot = + seed === 1 ? seed1Footprint : getRandomFootprint([seed, "AFootprint"]) + const bFoot = + seed === 1 ? seed1Footprint : getRandomFootprint([seed, "BFootprint"]) + const A = () => { + return + } + const B = () => { + const pcbX = Math.cos(rotation) * distance + const pcbY = Math.sin(rotation) * distance + return ( + + ) + } + + return ( + + + + port.${rand(seed, "aFrom").int(1, aFoot.pinCount)}`} + to={`.B > port.${rand(seed, "bFrom").int(1, bFoot.pinCount)}`} + /> + + ) +} + +export const SingleTraceMultilayerCircuit = ({ + seed, + distance, +}: SingleTrace2FootprintsProps) => { + // TODO randomly select a layout configuration using rand(seed).int(0, NUM_CONFIGURATIONS) + return +} diff --git a/module/lib/generators/single-trace-multilayer/index.tsx b/module/lib/generators/single-trace-multilayer/index.tsx new file mode 100644 index 0000000..ad9789a --- /dev/null +++ b/module/lib/generators/single-trace-multilayer/index.tsx @@ -0,0 +1,22 @@ +import type { AnySoupElement } from "@tscircuit/soup" +import { renderCircuitToSoup } from "../../generator-utils/renderCircuitToSoup" +import type { ProblemGenerator } from "../types" +import { SingleTraceMultilayerCircuit } from "./SingleTraceMultilayerCircuit" +import { replaceTracesWithErrors } from "../../generator-utils/replaceTracesWithErrors" +import { withCheckRegenerate } from "../utils/with-check-regenerate" + +export const getSingleTraceMultilayerProblemGenerator = + (): ProblemGenerator => { + const generateSingleTraceMultilayerProblem: ProblemGenerator["getExample"] = + async ({ seed }): Promise => { + return replaceTracesWithErrors( + await renderCircuitToSoup( + , + ), + ) + } + + return { + getExample: withCheckRegenerate(generateSingleTraceMultilayerProblem), + } + } diff --git a/module/lib/generators/types.ts b/module/lib/generators/types.ts index 98a8e4b..5034362 100644 --- a/module/lib/generators/types.ts +++ b/module/lib/generators/types.ts @@ -1,6 +1,10 @@ import type { AnySoupElement } from "@tscircuit/soup" -export type ProblemType = "single-trace" | "traces" | "distant-single-trace" +export type ProblemType = + | "single-trace" + | "traces" + | "distant-single-trace" + | "single-trace-multilayer" export type ProblemGenerator = { getExample: (params: { seed: number }) => Promise diff --git a/module/lib/server/available-datasets.ts b/module/lib/server/available-datasets.ts index 1de4514..d91b35c 100644 --- a/module/lib/server/available-datasets.ts +++ b/module/lib/server/available-datasets.ts @@ -2,4 +2,5 @@ export const AVAILABLE_DATASETS = [ "single-trace", "traces", "distant-single-trace", + "single-trace-multilayer", ] diff --git a/module/lib/solver-utils/SimpleRouteJson.ts b/module/lib/solver-utils/SimpleRouteJson.ts index 043472f..2670bee 100644 --- a/module/lib/solver-utils/SimpleRouteJson.ts +++ b/module/lib/solver-utils/SimpleRouteJson.ts @@ -2,7 +2,7 @@ import type { Obstacle } from "../types" export interface SimpleRouteConnection { name: string - pointsToConnect: Array<{ x: number; y: number }> + pointsToConnect: Array<{ x: number; y: number; layer: string }> } export interface SimpleRouteJson { diff --git a/module/lib/solver-utils/getObstaclesFromCircuitJson.ts b/module/lib/solver-utils/getObstaclesFromCircuitJson.ts index 41564ba..11ea43c 100644 --- a/module/lib/solver-utils/getObstaclesFromCircuitJson.ts +++ b/module/lib/solver-utils/getObstaclesFromCircuitJson.ts @@ -2,6 +2,8 @@ import type { AnySoupElement } from "@tscircuit/soup" import type { Obstacle } from "../types" import { getObstaclesFromRoute } from "./getObstaclesFromRoute" +const EVERY_LAYER = ["top", "inner1", "inner2", "bottom"] + export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { const obstacles: Obstacle[] = [] for (const element of soup) { @@ -10,6 +12,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { obstacles.push({ // @ts-ignore type: "oval", + layers: [element.layer], center: { x: element.x, y: element.y, @@ -21,6 +24,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { } else if (element.shape === "rect") { obstacles.push({ type: "rect", + layers: [element.layer], center: { x: element.x, y: element.y, @@ -35,6 +39,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { obstacles.push({ // @ts-ignore type: "oval", + layers: element.layers, center: { x: element.center.x, y: element.center.y, @@ -46,9 +51,10 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { } else if (element.shape === "rect") { obstacles.push({ type: "rect", + layers: element.layers, center: { - x: element.x, - y: element.y, + x: element.center.x, + y: element.center.y, }, width: element.width, height: element.height, @@ -71,6 +77,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { } else if (element.hole_shape === "square") { obstacles.push({ type: "rect", + layers: EVERY_LAYER, center: { x: element.x, y: element.y, @@ -82,6 +89,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { } else if (element.hole_shape === "round") { obstacles.push({ type: "rect", + layers: EVERY_LAYER, center: { x: element.x, y: element.y, @@ -96,6 +104,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { obstacles.push({ // @ts-ignore type: "oval", + layers: EVERY_LAYER, center: { x: element.x, y: element.y, @@ -108,6 +117,7 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { obstacles.push({ // @ts-ignore type: "oval", + layers: EVERY_LAYER, center: { x: element.x, y: element.y, @@ -119,7 +129,11 @@ export const getObstaclesFromCircuitJson = (soup: AnySoupElement[]) => { } } else if (element.type === "pcb_trace") { const traceObstacles = getObstaclesFromRoute( - element.route, + element.route.map((rp) => ({ + x: rp.x, + y: rp.y, + layer: "layer" in rp ? rp.layer : rp.from_layer, + })), element.source_trace_id!, ) obstacles.push(...traceObstacles) diff --git a/module/lib/solver-utils/getObstaclesFromRoute.ts b/module/lib/solver-utils/getObstaclesFromRoute.ts index 8901e07..71694ca 100644 --- a/module/lib/solver-utils/getObstaclesFromRoute.ts +++ b/module/lib/solver-utils/getObstaclesFromRoute.ts @@ -3,6 +3,7 @@ import type { Obstacle } from "autorouting-dataset/lib/types" interface Point { x: number y: number + layer: string } export const getObstaclesFromRoute = ( @@ -24,6 +25,7 @@ export const getObstaclesFromRoute = ( const obstacle: Obstacle = { type: "rect", + layers: [start.layer], center: { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2, diff --git a/module/lib/solver-utils/getSimpleRouteJson.ts b/module/lib/solver-utils/getSimpleRouteJson.ts index 593f5a3..173a47a 100644 --- a/module/lib/solver-utils/getSimpleRouteJson.ts +++ b/module/lib/solver-utils/getSimpleRouteJson.ts @@ -30,6 +30,7 @@ export const getSimpleRouteJson = (soup: AnySoupElement[]): SimpleRouteJson => { return { x: pcb_port.x, y: pcb_port.y, + layer: pcb_port.layers?.[0] ?? "top", } }), } diff --git a/module/lib/types.ts b/module/lib/types.ts index 6fefc37..c72c1b6 100644 --- a/module/lib/types.ts +++ b/module/lib/types.ts @@ -18,6 +18,7 @@ export interface Point { export type Obstacle = { // TODO include ovals type: "rect" // NOTE: most datasets do not contain ovals + layers: string[] center: { x: number; y: number } width: number height: number diff --git a/module/tests/fixtures/preload.ts b/module/tests/fixtures/preload.ts new file mode 100644 index 0000000..ee67a60 --- /dev/null +++ b/module/tests/fixtures/preload.ts @@ -0,0 +1 @@ +import "bun-match-svg" diff --git a/module/tests/getObstaclesFromCircuitJson.test.ts b/module/tests/getObstaclesFromCircuitJson.test.ts index 8f7d552..9f0f025 100644 --- a/module/tests/getObstaclesFromCircuitJson.test.ts +++ b/module/tests/getObstaclesFromCircuitJson.test.ts @@ -26,12 +26,14 @@ test("pcb_trace becomes an obstacle correctly", () => { center: { x: 5, y: 0 }, width: 10, height: 0.1, + layers: ["top"], connectedTo: ["trace1"], }) // Check the second obstacle (vertical trace) expect(obstacles[1]).toEqual({ type: "rect", + layers: ["top"], center: { x: 10, y: 5 }, width: 0.1, height: 10, diff --git a/package.json b/package.json index 12e9b44..cf8db67 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "@tscircuit/builder": "1.11.2", "@tscircuit/pcb-viewer": "1.4.5", "@tscircuit/props": "^0.0.26", - "@tscircuit/soup": "^0.0.66", - "@tscircuit/soup-util": "^0.0.21", + "@tscircuit/soup": "^0.0.68", + "@tscircuit/soup-util": "^0.0.23", "@types/bun": "latest", "@types/d3-delaunay": "^6.0.4", "@types/debug": "^4.1.12", @@ -29,6 +29,8 @@ "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", + "bun-match-svg": "^0.0.3", + "circuit-to-svg": "^0.0.22", "concurrently": "^8.2.2", "d3-delaunay": "^6.0.4", "debug": "^4.3.6",