@tscircuit/core 0.0.48 → 0.0.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts
CHANGED
|
@@ -3771,7 +3771,7 @@ declare class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
|
|
|
3771
3771
|
}>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
|
|
3772
3772
|
name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
|
|
3773
3773
|
}>>;
|
|
3774
|
-
}, "
|
|
3774
|
+
}, "layer" | "pcbRotation">, {
|
|
3775
3775
|
name: zod.ZodOptional<zod.ZodString>;
|
|
3776
3776
|
shape: zod.ZodLiteral<"circle">;
|
|
3777
3777
|
holeDiameter: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
|
|
@@ -3806,7 +3806,7 @@ declare class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
|
|
|
3806
3806
|
}>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
|
|
3807
3807
|
name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
|
|
3808
3808
|
}>>;
|
|
3809
|
-
}, "
|
|
3809
|
+
}, "layer" | "pcbRotation">, {
|
|
3810
3810
|
name: zod.ZodOptional<zod.ZodString>;
|
|
3811
3811
|
shape: zod.ZodLiteral<"oval">;
|
|
3812
3812
|
outerWidth: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
|
package/dist/index.js
CHANGED
|
@@ -2439,6 +2439,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2439
2439
|
this.renderError(
|
|
2440
2440
|
`Could not find a common layer (using hints) for trace ${this.getString()}`
|
|
2441
2441
|
);
|
|
2442
|
+
return;
|
|
2442
2443
|
}
|
|
2443
2444
|
const obstacles = getObstaclesFromSoup(this.root.db.toArray());
|
|
2444
2445
|
markObstaclesAsConnected(
|
|
@@ -2468,6 +2469,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2468
2469
|
});
|
|
2469
2470
|
const routes = [];
|
|
2470
2471
|
for (const [a, b] of pairs(orderedRoutePoints)) {
|
|
2472
|
+
const dominantLayer = "via_to_layer" in a ? a.via_to_layer : null;
|
|
2471
2473
|
const BOUNDS_MARGIN = 2;
|
|
2472
2474
|
const ijump = new IJumpAutorouter({
|
|
2473
2475
|
OBSTACLE_MARGIN: 0.3,
|
|
@@ -2476,10 +2478,13 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2476
2478
|
connections: [
|
|
2477
2479
|
{
|
|
2478
2480
|
name: this.source_trace_id,
|
|
2479
|
-
pointsToConnect: [
|
|
2481
|
+
pointsToConnect: [
|
|
2482
|
+
{ ...a, layer: dominantLayer ?? "top" },
|
|
2483
|
+
{ ...b, layer: dominantLayer ?? "top" }
|
|
2484
|
+
]
|
|
2480
2485
|
}
|
|
2481
2486
|
],
|
|
2482
|
-
layerCount:
|
|
2487
|
+
layerCount: 2,
|
|
2483
2488
|
bounds: {
|
|
2484
2489
|
minX: Math.min(a.x, b.x) - BOUNDS_MARGIN,
|
|
2485
2490
|
maxX: Math.max(a.x, b.x) + BOUNDS_MARGIN,
|
|
@@ -2490,16 +2495,53 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2490
2495
|
});
|
|
2491
2496
|
const traces = ijump.solveAndMapToTraces();
|
|
2492
2497
|
if (traces.length === 0) {
|
|
2493
|
-
|
|
2494
|
-
`Could not find a route between ${a} and ${b} for ${this}
|
|
2498
|
+
this.renderError(
|
|
2499
|
+
`Could not find a route between ${JSON.stringify(a)} and ${JSON.stringify(b)} for ${this}`
|
|
2495
2500
|
);
|
|
2496
2501
|
return;
|
|
2497
2502
|
}
|
|
2498
2503
|
const [trace] = traces;
|
|
2504
|
+
if (dominantLayer) {
|
|
2505
|
+
trace.route = trace.route.map((p) => {
|
|
2506
|
+
if (p.route_type === "wire") {
|
|
2507
|
+
p.layer = dominantLayer;
|
|
2508
|
+
}
|
|
2509
|
+
return p;
|
|
2510
|
+
});
|
|
2511
|
+
}
|
|
2499
2512
|
routes.push(trace.route);
|
|
2500
2513
|
}
|
|
2514
|
+
const mergedRoute = mergeRoutes(routes);
|
|
2515
|
+
const routeWithVias = mergedRoute.flatMap((point, index) => {
|
|
2516
|
+
const nextPoint = mergedRoute[index + 1];
|
|
2517
|
+
if (!nextPoint) return [point];
|
|
2518
|
+
if (point.route_type === "wire" && nextPoint.route_type === "wire" && point.layer !== nextPoint.layer) {
|
|
2519
|
+
return [
|
|
2520
|
+
{
|
|
2521
|
+
route_type: "via",
|
|
2522
|
+
from_layer: point.layer,
|
|
2523
|
+
to_layer: nextPoint.layer,
|
|
2524
|
+
x: nextPoint.x,
|
|
2525
|
+
y: nextPoint.y
|
|
2526
|
+
},
|
|
2527
|
+
point
|
|
2528
|
+
];
|
|
2529
|
+
}
|
|
2530
|
+
return [point];
|
|
2531
|
+
});
|
|
2532
|
+
for (const via of routeWithVias.filter((p) => p.route_type === "via")) {
|
|
2533
|
+
db.pcb_via.insert({
|
|
2534
|
+
x: via.x,
|
|
2535
|
+
y: via.y,
|
|
2536
|
+
hole_diameter: 0.3,
|
|
2537
|
+
outer_diameter: 0.6,
|
|
2538
|
+
layers: [via.from_layer, via.to_layer],
|
|
2539
|
+
from_layer: via.from_layer,
|
|
2540
|
+
to_layer: via.to_layer
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2501
2543
|
const pcb_trace = db.pcb_trace.insert({
|
|
2502
|
-
route:
|
|
2544
|
+
route: routeWithVias,
|
|
2503
2545
|
source_trace_id: this.source_trace_id
|
|
2504
2546
|
});
|
|
2505
2547
|
this._portsRoutedOnPcb = ports;
|
|
@@ -2520,6 +2562,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2520
2562
|
if (elm.type === "schematic_component") {
|
|
2521
2563
|
obstacles.push({
|
|
2522
2564
|
type: "rect",
|
|
2565
|
+
layers: ["top"],
|
|
2523
2566
|
center: elm.center,
|
|
2524
2567
|
width: elm.size.width,
|
|
2525
2568
|
height: elm.size.height,
|
|
@@ -2528,13 +2571,14 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2528
2571
|
}
|
|
2529
2572
|
}
|
|
2530
2573
|
for (const { port } of ports) {
|
|
2531
|
-
connection.pointsToConnect.push(
|
|
2532
|
-
projectPointInDirection(
|
|
2574
|
+
connection.pointsToConnect.push({
|
|
2575
|
+
...projectPointInDirection(
|
|
2533
2576
|
port._getGlobalSchematicPositionBeforeLayout(),
|
|
2534
2577
|
port.facingDirection,
|
|
2535
2578
|
0.1501
|
|
2536
|
-
)
|
|
2537
|
-
|
|
2579
|
+
),
|
|
2580
|
+
layer: "top"
|
|
2581
|
+
});
|
|
2538
2582
|
}
|
|
2539
2583
|
const bounds = computeObstacleBounds(obstacles);
|
|
2540
2584
|
const simpleRouteJsonInput = {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "@tscircuit/infgrid-ijump-astar"
|
|
10
10
|
import type {
|
|
11
11
|
AnySoupElement,
|
|
12
|
+
LayerRef,
|
|
12
13
|
PCBTrace,
|
|
13
14
|
RouteHintPoint,
|
|
14
15
|
SchematicTrace,
|
|
@@ -366,6 +367,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
366
367
|
this.renderError(
|
|
367
368
|
`Could not find a common layer (using hints) for trace ${this.getString()}`,
|
|
368
369
|
)
|
|
370
|
+
return
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
// Cache the PCB obstacles, they'll be needed for each segment between
|
|
@@ -409,7 +411,10 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
409
411
|
|
|
410
412
|
const routes: PCBTrace["route"][] = []
|
|
411
413
|
for (const [a, b] of pairs(orderedRoutePoints)) {
|
|
414
|
+
const dominantLayer =
|
|
415
|
+
"via_to_layer" in a ? (a.via_to_layer as LayerRef) : null
|
|
412
416
|
const BOUNDS_MARGIN = 2 //mm
|
|
417
|
+
|
|
413
418
|
const ijump = new IJumpAutorouter({
|
|
414
419
|
OBSTACLE_MARGIN: 0.3,
|
|
415
420
|
input: {
|
|
@@ -417,10 +422,13 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
417
422
|
connections: [
|
|
418
423
|
{
|
|
419
424
|
name: this.source_trace_id!,
|
|
420
|
-
pointsToConnect: [
|
|
425
|
+
pointsToConnect: [
|
|
426
|
+
{ ...a, layer: dominantLayer ?? "top" },
|
|
427
|
+
{ ...b, layer: dominantLayer ?? "top" },
|
|
428
|
+
],
|
|
421
429
|
},
|
|
422
430
|
],
|
|
423
|
-
layerCount:
|
|
431
|
+
layerCount: 2,
|
|
424
432
|
bounds: {
|
|
425
433
|
minX: Math.min(a.x, b.x) - BOUNDS_MARGIN,
|
|
426
434
|
maxX: Math.max(a.x, b.x) + BOUNDS_MARGIN,
|
|
@@ -431,18 +439,67 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
431
439
|
})
|
|
432
440
|
const traces = ijump.solveAndMapToTraces()
|
|
433
441
|
if (traces.length === 0) {
|
|
434
|
-
|
|
435
|
-
`Could not find a route between ${a} and ${b} for ${this}
|
|
442
|
+
this.renderError(
|
|
443
|
+
`Could not find a route between ${JSON.stringify(a)} and ${JSON.stringify(b)} for ${this}`,
|
|
436
444
|
)
|
|
437
445
|
return
|
|
438
446
|
}
|
|
439
447
|
// TODO ijump returns multiple traces for some reason
|
|
440
448
|
const [trace] = traces as PCBTrace[]
|
|
449
|
+
// TODO ijump always returns on top layer and has no multilayer support
|
|
450
|
+
// https://github.com/tscircuit/autorouting-dataset/issues/35
|
|
451
|
+
// For now, we'll move the trace to whatever layer the first point
|
|
452
|
+
// specifies we should have "via'd" to
|
|
453
|
+
if (dominantLayer) {
|
|
454
|
+
trace.route = trace.route.map((p) => {
|
|
455
|
+
if (p.route_type === "wire") {
|
|
456
|
+
p.layer = dominantLayer
|
|
457
|
+
}
|
|
458
|
+
return p
|
|
459
|
+
})
|
|
460
|
+
}
|
|
441
461
|
routes.push(trace.route)
|
|
442
462
|
}
|
|
443
463
|
|
|
464
|
+
const mergedRoute = mergeRoutes(routes)
|
|
465
|
+
|
|
466
|
+
// Add vias where layer changes occur
|
|
467
|
+
const routeWithVias = mergedRoute.flatMap((point, index) => {
|
|
468
|
+
const nextPoint = mergedRoute[index + 1]
|
|
469
|
+
if (!nextPoint) return [point]
|
|
470
|
+
if (
|
|
471
|
+
point.route_type === "wire" &&
|
|
472
|
+
nextPoint.route_type === "wire" &&
|
|
473
|
+
point.layer !== nextPoint.layer
|
|
474
|
+
) {
|
|
475
|
+
return [
|
|
476
|
+
{
|
|
477
|
+
route_type: "via",
|
|
478
|
+
from_layer: point.layer,
|
|
479
|
+
to_layer: nextPoint.layer,
|
|
480
|
+
x: nextPoint.x,
|
|
481
|
+
y: nextPoint.y,
|
|
482
|
+
} as (typeof mergedRoute)[number],
|
|
483
|
+
point,
|
|
484
|
+
]
|
|
485
|
+
}
|
|
486
|
+
return [point]
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
for (const via of routeWithVias.filter((p) => p.route_type === "via")) {
|
|
490
|
+
db.pcb_via.insert({
|
|
491
|
+
x: via.x,
|
|
492
|
+
y: via.y,
|
|
493
|
+
hole_diameter: 0.3,
|
|
494
|
+
outer_diameter: 0.6,
|
|
495
|
+
layers: [via.from_layer as LayerRef, via.to_layer as LayerRef],
|
|
496
|
+
from_layer: via.from_layer as LayerRef,
|
|
497
|
+
to_layer: via.to_layer as LayerRef,
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
|
|
444
501
|
const pcb_trace = db.pcb_trace.insert({
|
|
445
|
-
route:
|
|
502
|
+
route: routeWithVias,
|
|
446
503
|
source_trace_id: this.source_trace_id!,
|
|
447
504
|
})
|
|
448
505
|
this._portsRoutedOnPcb = ports
|
|
@@ -470,6 +527,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
470
527
|
if (elm.type === "schematic_component") {
|
|
471
528
|
obstacles.push({
|
|
472
529
|
type: "rect",
|
|
530
|
+
layers: ["top"],
|
|
473
531
|
center: elm.center,
|
|
474
532
|
width: elm.size.width,
|
|
475
533
|
height: elm.size.height,
|
|
@@ -479,13 +537,14 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
479
537
|
}
|
|
480
538
|
|
|
481
539
|
for (const { port } of ports) {
|
|
482
|
-
connection.pointsToConnect.push(
|
|
483
|
-
projectPointInDirection(
|
|
540
|
+
connection.pointsToConnect.push({
|
|
541
|
+
...projectPointInDirection(
|
|
484
542
|
port._getGlobalSchematicPositionBeforeLayout(),
|
|
485
543
|
port.facingDirection!,
|
|
486
544
|
0.1501,
|
|
487
545
|
),
|
|
488
|
-
|
|
546
|
+
layer: "top",
|
|
547
|
+
})
|
|
489
548
|
}
|
|
490
549
|
|
|
491
550
|
const bounds = computeObstacleBounds(obstacles)
|
|
@@ -12,6 +12,7 @@ export type SimplifiedPcbTrace = {
|
|
|
12
12
|
export type Obstacle = {
|
|
13
13
|
// TODO include ovals
|
|
14
14
|
type: "rect" // NOTE: most datasets do not contain ovals
|
|
15
|
+
layers: string[]
|
|
15
16
|
center: { x: number; y: number }
|
|
16
17
|
width: number
|
|
17
18
|
height: number
|
|
@@ -20,7 +21,7 @@ export type Obstacle = {
|
|
|
20
21
|
|
|
21
22
|
export interface SimpleRouteConnection {
|
|
22
23
|
name: string
|
|
23
|
-
pointsToConnect: Array<{ x: number; y: number }>
|
|
24
|
+
pointsToConnect: Array<{ x: number; y: number; layer: string }>
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface SimpleRouteJson {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.50",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"files": [
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"@types/react": "^18.3.3",
|
|
24
24
|
"@types/react-reconciler": "^0.28.8",
|
|
25
25
|
"bun-match-svg": "0.0.2",
|
|
26
|
-
"circuit-to-svg": "^0.0.
|
|
26
|
+
"circuit-to-svg": "^0.0.22",
|
|
27
27
|
"debug": "^4.3.6",
|
|
28
28
|
"howfat": "^0.3.8",
|
|
29
29
|
"looks-same": "^9.0.1",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@lume/kiwi": "^0.4.3",
|
|
37
|
-
"@tscircuit/infgrid-ijump-astar": "^0.0.
|
|
37
|
+
"@tscircuit/infgrid-ijump-astar": "^0.0.10",
|
|
38
38
|
"@tscircuit/props": "^0.0.62",
|
|
39
39
|
"@tscircuit/soup": "^0.0.67",
|
|
40
40
|
"@tscircuit/soup-util": "^0.0.23",
|