@tscircuit/core 0.0.58 → 0.0.60

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
@@ -3773,7 +3773,7 @@ declare class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
3773
3773
  }>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
3774
3774
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
3775
3775
  }>>;
3776
- }, "layer" | "pcbRotation">, {
3776
+ }, "pcbRotation" | "layer">, {
3777
3777
  name: zod.ZodOptional<zod.ZodString>;
3778
3778
  shape: zod.ZodLiteral<"circle">;
3779
3779
  holeDiameter: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
@@ -3808,7 +3808,7 @@ declare class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
3808
3808
  }>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
3809
3809
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
3810
3810
  }>>;
3811
- }, "layer" | "pcbRotation">, {
3811
+ }, "pcbRotation" | "layer">, {
3812
3812
  name: zod.ZodOptional<zod.ZodString>;
3813
3813
  shape: zod.ZodLiteral<"oval">;
3814
3814
  outerWidth: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
package/dist/index.js CHANGED
@@ -1693,6 +1693,13 @@ var NormalComponent = class extends PrimitiveComponent {
1693
1693
  if (!footprint) return;
1694
1694
  if (typeof footprint === "string") {
1695
1695
  const fpSoup = fp.string(footprint).soup();
1696
+ if (this.props.layer) {
1697
+ for (const elm of fpSoup) {
1698
+ if ("layer" in elm) {
1699
+ elm.layer = this.props.layer;
1700
+ }
1701
+ }
1702
+ }
1696
1703
  const fpComponents = createComponentsFromSoup(fpSoup);
1697
1704
  this.addAll(fpComponents);
1698
1705
  }
@@ -2250,6 +2257,7 @@ var portToObjective = (port) => {
2250
2257
  layers: port.getAvailablePcbLayers()
2251
2258
  };
2252
2259
  };
2260
+ var SHOULD_USE_SINGLE_LAYER_ROUTING = false;
2253
2261
  var Trace = class extends PrimitiveComponent {
2254
2262
  source_trace_id = null;
2255
2263
  pcb_trace_id = null;
@@ -2464,7 +2472,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2464
2472
  const candidateLayerCombinations = findPossibleTraceLayerCombinations(
2465
2473
  orderedRouteObjectives
2466
2474
  );
2467
- if (candidateLayerCombinations.length === 0) {
2475
+ if (SHOULD_USE_SINGLE_LAYER_ROUTING && candidateLayerCombinations.length === 0) {
2468
2476
  this.renderError(
2469
2477
  `Could not find a common layer (using hints) for trace ${this.getString()}`
2470
2478
  );
@@ -2498,32 +2506,38 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2498
2506
  }
2499
2507
  }
2500
2508
  }
2501
- const candidateLayerSelections = candidateLayerCombinations[0].layer_path;
2502
- const orderedRoutePoints = orderedRouteObjectives.map((t, idx) => {
2503
- if (t.via) {
2504
- return {
2505
- ...t,
2506
- via_to_layer: candidateLayerSelections[idx]
2507
- };
2508
- }
2509
- return { ...t, layers: [candidateLayerSelections[idx]] };
2510
- });
2509
+ let orderedRoutePoints = [];
2510
+ if (candidateLayerCombinations.length === 0) {
2511
+ orderedRoutePoints = orderedRouteObjectives;
2512
+ } else {
2513
+ const candidateLayerSelections = candidateLayerCombinations[0].layer_path;
2514
+ orderedRoutePoints = orderedRouteObjectives.map((t, idx) => {
2515
+ if (t.via) {
2516
+ return {
2517
+ ...t,
2518
+ via_to_layer: candidateLayerSelections[idx]
2519
+ };
2520
+ }
2521
+ return { ...t, layers: [candidateLayerSelections[idx]] };
2522
+ });
2523
+ }
2511
2524
  const routes = [];
2512
2525
  for (const [a, b] of pairs(orderedRoutePoints)) {
2513
2526
  const dominantLayer = "via_to_layer" in a ? a.via_to_layer : null;
2514
2527
  const BOUNDS_MARGIN = 2;
2528
+ const aLayer = "layers" in a && a.layers.length === 1 ? a.layers[0] : dominantLayer ?? "top";
2529
+ const bLayer = "layers" in b && b.layers.length === 1 ? b.layers[0] : dominantLayer ?? "top";
2515
2530
  const ijump = new MultilayerIjump({
2516
2531
  OBSTACLE_MARGIN: 0.3,
2517
2532
  isRemovePathLoopsEnabled: true,
2518
- layerCount: 2,
2519
2533
  input: {
2520
2534
  obstacles,
2521
2535
  connections: [
2522
2536
  {
2523
2537
  name: connMap.getNetConnectedToId(this.source_trace_id),
2524
2538
  pointsToConnect: [
2525
- { ...a, layer: dominantLayer ?? "top" },
2526
- { ...b, layer: dominantLayer ?? "top" }
2539
+ { ...a, layer: aLayer },
2540
+ { ...b, layer: bLayer }
2527
2541
  ]
2528
2542
  }
2529
2543
  ],
@@ -2577,36 +2591,21 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2577
2591
  routes.push(trace.route);
2578
2592
  }
2579
2593
  const mergedRoute = mergeRoutes(routes);
2580
- const routeWithVias = mergedRoute.flatMap((point, index) => {
2581
- const nextPoint = mergedRoute[index + 1];
2582
- if (!nextPoint) return [point];
2583
- if (point.route_type === "wire" && nextPoint.route_type === "wire" && point.layer !== nextPoint.layer) {
2584
- return [
2585
- {
2586
- route_type: "via",
2587
- from_layer: point.layer,
2588
- to_layer: nextPoint.layer,
2589
- x: nextPoint.x,
2590
- y: nextPoint.y
2591
- },
2592
- point
2593
- ];
2594
+ for (const point of mergedRoute) {
2595
+ if (point.route_type === "via") {
2596
+ db.pcb_via.insert({
2597
+ x: point.x,
2598
+ y: point.y,
2599
+ hole_diameter: 0.3,
2600
+ outer_diameter: 0.6,
2601
+ layers: [point.from_layer, point.to_layer],
2602
+ from_layer: point.from_layer,
2603
+ to_layer: point.to_layer
2604
+ });
2594
2605
  }
2595
- return [point];
2596
- });
2597
- for (const via of routeWithVias.filter((p) => p.route_type === "via")) {
2598
- db.pcb_via.insert({
2599
- x: via.x,
2600
- y: via.y,
2601
- hole_diameter: 0.3,
2602
- outer_diameter: 0.6,
2603
- layers: [via.from_layer, via.to_layer],
2604
- from_layer: via.from_layer,
2605
- to_layer: via.to_layer
2606
- });
2607
2606
  }
2608
2607
  const pcb_trace = db.pcb_trace.insert({
2609
- route: routeWithVias,
2608
+ route: mergedRoute,
2610
2609
  source_trace_id: this.source_trace_id
2611
2610
  });
2612
2611
  this._portsRoutedOnPcb = ports;
@@ -119,6 +119,14 @@ export class NormalComponent<
119
119
  if (!footprint) return
120
120
  if (typeof footprint === "string") {
121
121
  const fpSoup = fp.string(footprint).soup()
122
+ // Adjust the layer of the footprint to match the layer of the component
123
+ if (this.props.layer) {
124
+ for (const elm of fpSoup) {
125
+ if ("layer" in elm) {
126
+ elm.layer = this.props.layer
127
+ }
128
+ }
129
+ }
122
130
  const fpComponents = createComponentsFromSoup(fpSoup)
123
131
  this.addAll(fpComponents)
124
132
  }
@@ -54,6 +54,8 @@ const portToObjective = (port: Port): PcbRouteObjective => {
54
54
  }
55
55
  }
56
56
 
57
+ const SHOULD_USE_SINGLE_LAYER_ROUTING = false
58
+
57
59
  export class Trace extends PrimitiveComponent<typeof traceProps> {
58
60
  source_trace_id: string | null = null
59
61
  pcb_trace_id: string | null = null
@@ -355,7 +357,10 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
355
357
  orderedRouteObjectives,
356
358
  )
357
359
 
358
- if (candidateLayerCombinations.length === 0) {
360
+ if (
361
+ SHOULD_USE_SINGLE_LAYER_ROUTING &&
362
+ candidateLayerCombinations.length === 0
363
+ ) {
359
364
  this.renderError(
360
365
  `Could not find a common layer (using hints) for trace ${this.getString()}`,
361
366
  )
@@ -396,22 +401,27 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
396
401
  }
397
402
  }
398
403
 
399
- // TODO explore all candidate layer combinations if one fails
400
- const candidateLayerSelections = candidateLayerCombinations[0].layer_path
401
-
402
- /**
403
- * Apply the candidate layer selections to the route objectives, now we
404
- * have a set of points that have definite layers
405
- */
406
- const orderedRoutePoints = orderedRouteObjectives.map((t, idx) => {
407
- if (t.via) {
408
- return {
409
- ...t,
410
- via_to_layer: candidateLayerSelections[idx],
404
+ let orderedRoutePoints: PcbRouteObjective[] = []
405
+ if (candidateLayerCombinations.length === 0) {
406
+ orderedRoutePoints = orderedRouteObjectives
407
+ } else {
408
+ // TODO explore all candidate layer combinations if one fails
409
+ const candidateLayerSelections = candidateLayerCombinations[0].layer_path
410
+
411
+ /**
412
+ * Apply the candidate layer selections to the route objectives, now we
413
+ * have a set of points that have definite layers
414
+ */
415
+ orderedRoutePoints = orderedRouteObjectives.map((t, idx) => {
416
+ if (t.via) {
417
+ return {
418
+ ...t,
419
+ via_to_layer: candidateLayerSelections[idx],
420
+ }
411
421
  }
412
- }
413
- return { ...t, layers: [candidateLayerSelections[idx]] }
414
- })
422
+ return { ...t, layers: [candidateLayerSelections[idx]] }
423
+ })
424
+ }
415
425
 
416
426
  const routes: PCBTrace["route"][] = []
417
427
  for (const [a, b] of pairs(orderedRoutePoints)) {
@@ -419,18 +429,26 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
419
429
  "via_to_layer" in a ? (a.via_to_layer as LayerRef) : null
420
430
  const BOUNDS_MARGIN = 2 //mm
421
431
 
432
+ const aLayer =
433
+ "layers" in a && a.layers.length === 1
434
+ ? a.layers[0]
435
+ : dominantLayer ?? "top"
436
+ const bLayer =
437
+ "layers" in b && b.layers.length === 1
438
+ ? b.layers[0]
439
+ : dominantLayer ?? "top"
440
+
422
441
  const ijump = new MultilayerIjump({
423
442
  OBSTACLE_MARGIN: 0.3,
424
443
  isRemovePathLoopsEnabled: true,
425
- layerCount: 2,
426
444
  input: {
427
445
  obstacles,
428
446
  connections: [
429
447
  {
430
448
  name: connMap.getNetConnectedToId(this.source_trace_id!)!,
431
449
  pointsToConnect: [
432
- { ...a, layer: dominantLayer ?? "top" },
433
- { ...b, layer: dominantLayer ?? "top" },
450
+ { ...a, layer: aLayer },
451
+ { ...b, layer: bLayer },
434
452
  ],
435
453
  },
436
454
  ],
@@ -491,43 +509,22 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
491
509
 
492
510
  const mergedRoute = mergeRoutes(routes)
493
511
 
494
- // Add vias where layer changes occur
495
- const routeWithVias = mergedRoute.flatMap((point, index) => {
496
- const nextPoint = mergedRoute[index + 1]
497
- if (!nextPoint) return [point]
498
- if (
499
- point.route_type === "wire" &&
500
- nextPoint.route_type === "wire" &&
501
- point.layer !== nextPoint.layer
502
- ) {
503
- return [
504
- {
505
- route_type: "via",
506
- from_layer: point.layer,
507
- to_layer: nextPoint.layer,
508
- x: nextPoint.x,
509
- y: nextPoint.y,
510
- } as (typeof mergedRoute)[number],
511
- point,
512
- ]
512
+ for (const point of mergedRoute) {
513
+ if (point.route_type === "via") {
514
+ db.pcb_via.insert({
515
+ x: point.x,
516
+ y: point.y,
517
+ hole_diameter: 0.3,
518
+ outer_diameter: 0.6,
519
+ layers: [point.from_layer as LayerRef, point.to_layer as LayerRef],
520
+ from_layer: point.from_layer as LayerRef,
521
+ to_layer: point.to_layer as LayerRef,
522
+ })
513
523
  }
514
- return [point]
515
- })
516
-
517
- for (const via of routeWithVias.filter((p) => p.route_type === "via")) {
518
- db.pcb_via.insert({
519
- x: via.x,
520
- y: via.y,
521
- hole_diameter: 0.3,
522
- outer_diameter: 0.6,
523
- layers: [via.from_layer as LayerRef, via.to_layer as LayerRef],
524
- from_layer: via.from_layer as LayerRef,
525
- to_layer: via.to_layer as LayerRef,
526
- })
527
524
  }
528
525
 
529
526
  const pcb_trace = db.pcb_trace.insert({
530
- route: routeWithVias,
527
+ route: mergedRoute,
531
528
  source_trace_id: this.source_trace_id!,
532
529
  })
533
530
  this._portsRoutedOnPcb = ports
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.58",
5
+ "version": "0.0.60",
6
6
  "types": "dist/index.d.ts",
7
7
  "main": "dist/index.js",
8
8
  "files": [
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@lume/kiwi": "^0.4.3",
37
- "@tscircuit/infgrid-ijump-astar": "^0.0.15",
37
+ "@tscircuit/infgrid-ijump-astar": "^0.0.16",
38
38
  "@tscircuit/props": "^0.0.62",
39
39
  "@tscircuit/soup": "^0.0.67",
40
40
  "@tscircuit/soup-util": "^0.0.23",