@tscircuit/core 0.0.134 → 0.0.135

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
@@ -106,6 +106,10 @@ declare class Circuit {
106
106
  */
107
107
  declare const Project: typeof Circuit;
108
108
 
109
+ interface ISubcircuit extends PrimitiveComponent {
110
+ _shouldUseTraceByTraceRouting(): boolean;
111
+ }
112
+
109
113
  interface BaseComponentConfig {
110
114
  componentName: string;
111
115
  schematicSymbolName?: BaseSymbolName | null;
@@ -256,7 +260,7 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
256
260
  height: number;
257
261
  };
258
262
  doesSelectorMatch(selector: string): boolean;
259
- getSubcircuit(): PrimitiveComponent;
263
+ getSubcircuit(): ISubcircuit;
260
264
  selectAll(selector: string): PrimitiveComponent[];
261
265
  selectOne(selector: string, options?: {
262
266
  type?: string;
@@ -309,6 +313,10 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
309
313
  * ports that are connected to each other. If a there are multiple net islands
310
314
  * that means that the net is not fully connected and we need to add traces
311
315
  * such that the nets are fully connected
316
+ *
317
+ * Sometimes this phase doesn't find any net islands if the autorouter did
318
+ * a good job and connected the islands. In some sense this is a "backup"
319
+ * routing phase for autorouters that don't care about connecting nets.
312
320
  */
313
321
  doInitialPcbRouteNetIslands(): void;
314
322
  }
@@ -730,13 +738,78 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
730
738
  doInitialCadModelRender(): void;
731
739
  }
732
740
 
733
- declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps> extends NormalComponent<Props> {
741
+ type SimplifiedPcbTrace = {
742
+ type: "pcb_trace";
743
+ pcb_trace_id: string;
744
+ route: Array<{
745
+ route_type: "wire";
746
+ x: number;
747
+ y: number;
748
+ width: number;
749
+ layer: string;
750
+ } | {
751
+ route_type: "via";
752
+ x: number;
753
+ y: number;
754
+ to_layer: string;
755
+ from_layer: string;
756
+ }>;
757
+ };
758
+ type Obstacle = {
759
+ type: "rect";
760
+ layers: string[];
761
+ center: {
762
+ x: number;
763
+ y: number;
764
+ };
765
+ width: number;
766
+ height: number;
767
+ connectedTo: string[];
768
+ };
769
+ interface SimpleRouteConnection {
770
+ name: string;
771
+ pointsToConnect: Array<{
772
+ x: number;
773
+ y: number;
774
+ layer: string;
775
+ }>;
776
+ }
777
+ interface SimpleRouteJson {
778
+ layerCount: number;
779
+ minTraceWidth: number;
780
+ obstacles: Obstacle[];
781
+ connections: Array<SimpleRouteConnection>;
782
+ bounds: {
783
+ minX: number;
784
+ maxX: number;
785
+ minY: number;
786
+ maxY: number;
787
+ };
788
+ traces?: SimplifiedPcbTrace[];
789
+ }
790
+
791
+ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps> extends NormalComponent<Props> implements ISubcircuit {
792
+ _asyncAutoroutingResult: {
793
+ output_simple_route_json: SimpleRouteJson;
794
+ } | null;
734
795
  get config(): {
735
796
  zodProps: Props;
736
797
  componentName: string;
737
798
  };
738
799
  doInitialCreateTraceHintsFromProps(): void;
800
+ _getSimpleRouteJsonFromPcbTraces(): SimpleRouteJson;
801
+ doInitialPcbTraceRender(): void;
802
+ updatePcbTraceRender(): void;
739
803
  doInitialSchematicLayout(): void;
804
+ /**
805
+ * Trace-by-trace autorouting is where each trace routes itself in a well-known
806
+ * order. It's the most deterministic way to autoroute, because a new trace
807
+ * is generally ordered last.
808
+ *
809
+ * This method will return false if using an external service for autorouting
810
+ * or if using a "fullview" or "rip and replace" autorouting mode
811
+ */
812
+ _shouldUseTraceByTraceRouting(): boolean;
740
813
  }
741
814
 
742
815
  declare class Board extends Group<typeof boardProps> {
package/dist/index.js CHANGED
@@ -903,6 +903,10 @@ var Net = class extends PrimitiveComponent {
903
903
  * ports that are connected to each other. If a there are multiple net islands
904
904
  * that means that the net is not fully connected and we need to add traces
905
905
  * such that the nets are fully connected
906
+ *
907
+ * Sometimes this phase doesn't find any net islands if the autorouter did
908
+ * a good job and connected the islands. In some sense this is a "backup"
909
+ * routing phase for autorouters that don't care about connecting nets.
906
910
  */
907
911
  doInitialPcbRouteNetIslands() {
908
912
  const { db } = this.root;
@@ -2433,7 +2437,7 @@ var NormalComponent = class extends PrimitiveComponent {
2433
2437
  import { boardProps } from "@tscircuit/props";
2434
2438
  import { identity as identity4 } from "transformation-matrix";
2435
2439
 
2436
- // lib/components/primitive-components/Group.ts
2440
+ // lib/components/primitive-components/Group/Group.ts
2437
2441
  import {
2438
2442
  groupProps
2439
2443
  } from "@tscircuit/props";
@@ -2500,9 +2504,11 @@ var TraceHint = class extends PrimitiveComponent {
2500
2504
  }
2501
2505
  };
2502
2506
 
2503
- // lib/components/primitive-components/Group.ts
2507
+ // lib/components/primitive-components/Group/Group.ts
2504
2508
  import * as SAL from "@tscircuit/schematic-autolayout";
2509
+ import { getObstaclesFromSoup } from "@tscircuit/infgrid-ijump-astar";
2505
2510
  var Group = class extends NormalComponent {
2511
+ _asyncAutoroutingResult = null;
2506
2512
  get config() {
2507
2513
  return {
2508
2514
  zodProps: groupProps,
@@ -2525,6 +2531,87 @@ var Group = class extends NormalComponent {
2525
2531
  );
2526
2532
  }
2527
2533
  }
2534
+ _getSimpleRouteJsonFromPcbTraces() {
2535
+ const traces = this.selectAll("trace");
2536
+ const { db } = this.root;
2537
+ const obstacles = getObstaclesFromSoup([
2538
+ ...db.pcb_component.list(),
2539
+ ...db.pcb_smtpad.list(),
2540
+ ...db.pcb_plated_hole.list()
2541
+ ]);
2542
+ const allPoints = obstacles.flatMap((o) => [
2543
+ {
2544
+ x: o.center.x - o.width / 2,
2545
+ y: o.center.y - o.height / 2
2546
+ },
2547
+ {
2548
+ x: o.center.x + o.width / 2,
2549
+ y: o.center.y + o.height / 2
2550
+ }
2551
+ ]);
2552
+ const bounds = {
2553
+ minX: Math.min(...allPoints.map((p) => p.x)) - 1,
2554
+ maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
2555
+ minY: Math.min(...allPoints.map((p) => p.y)) - 1,
2556
+ maxY: Math.max(...allPoints.map((p) => p.y)) + 1
2557
+ };
2558
+ const connections = traces.map((trace) => {
2559
+ const connectedPorts = trace._findConnectedPorts();
2560
+ if (!connectedPorts.allPortsFound || connectedPorts.ports.length < 2)
2561
+ return null;
2562
+ return {
2563
+ name: trace.source_trace_id ?? "",
2564
+ pointsToConnect: connectedPorts.ports.map((port) => {
2565
+ const pos = port._getGlobalPcbPositionBeforeLayout();
2566
+ return {
2567
+ x: pos.x,
2568
+ y: pos.y,
2569
+ layer: port.getAvailablePcbLayers()[0] ?? "top"
2570
+ };
2571
+ })
2572
+ };
2573
+ }).filter((c) => c !== null);
2574
+ return {
2575
+ bounds,
2576
+ obstacles: [],
2577
+ connections,
2578
+ layerCount: 2,
2579
+ minTraceWidth: this._parsedProps.minTraceWidth ?? 0.1
2580
+ };
2581
+ }
2582
+ doInitialPcbTraceRender() {
2583
+ if (this._shouldUseTraceByTraceRouting()) return;
2584
+ if (this.props.autorouter?.serverUrl) {
2585
+ this._queueAsyncEffect(async () => {
2586
+ const { autorouting_result } = await fetch(
2587
+ this.props.autorouter.serverUrl,
2588
+ {
2589
+ method: "POST",
2590
+ body: JSON.stringify({
2591
+ input_simple_route_json: this._getSimpleRouteJsonFromPcbTraces()
2592
+ })
2593
+ }
2594
+ ).then((r) => r.json());
2595
+ const { output_simple_route_json } = autorouting_result;
2596
+ this._asyncAutoroutingResult = autorouting_result;
2597
+ this._markDirty("PcbTraceRender");
2598
+ });
2599
+ }
2600
+ }
2601
+ updatePcbTraceRender() {
2602
+ if (!this._asyncAutoroutingResult) return;
2603
+ if (this._shouldUseTraceByTraceRouting()) return;
2604
+ const { db } = this.root;
2605
+ const { traces: routedTraces } = this._asyncAutoroutingResult.output_simple_route_json;
2606
+ if (!routedTraces) return;
2607
+ const circuitTraces = this.selectAll("trace");
2608
+ for (const routedTrace of routedTraces) {
2609
+ const pcb_trace = db.pcb_trace.insert({
2610
+ route: routedTrace.route
2611
+ // source_trace_id: circuitTrace.source_trace_id!,
2612
+ });
2613
+ }
2614
+ }
2528
2615
  doInitialSchematicLayout() {
2529
2616
  if (!this.isSubcircuit) return;
2530
2617
  const props = this._parsedProps;
@@ -2551,6 +2638,18 @@ var Group = class extends NormalComponent {
2551
2638
  const laidOutScene = SAL.ascendingCentralLrBug1(scene);
2552
2639
  SAL.mutateSoupForScene(db.toArray(), laidOutScene);
2553
2640
  }
2641
+ /**
2642
+ * Trace-by-trace autorouting is where each trace routes itself in a well-known
2643
+ * order. It's the most deterministic way to autoroute, because a new trace
2644
+ * is generally ordered last.
2645
+ *
2646
+ * This method will return false if using an external service for autorouting
2647
+ * or if using a "fullview" or "rip and replace" autorouting mode
2648
+ */
2649
+ _shouldUseTraceByTraceRouting() {
2650
+ if (this.props.autorouter) return false;
2651
+ return true;
2652
+ }
2554
2653
  };
2555
2654
 
2556
2655
  // lib/components/normal-components/Board.ts
@@ -2617,7 +2716,7 @@ var FTYPE = stringProxy;
2617
2716
  // lib/components/primitive-components/Trace.ts
2618
2717
  import {
2619
2718
  MultilayerIjump,
2620
- getObstaclesFromSoup
2719
+ getObstaclesFromSoup as getObstaclesFromSoup2
2621
2720
  } from "@tscircuit/infgrid-ijump-astar";
2622
2721
  import { traceProps } from "@tscircuit/props";
2623
2722
  import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map";
@@ -2998,6 +3097,9 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2998
3097
  if (this.getSubcircuit()._parsedProps.routingDisabled) {
2999
3098
  return;
3000
3099
  }
3100
+ if (!this.getSubcircuit()._shouldUseTraceByTraceRouting()) {
3101
+ return;
3102
+ }
3001
3103
  const { allPortsFound, ports } = this._findConnectedPorts();
3002
3104
  const portsConnectedOnPcbViaNet = [];
3003
3105
  if (!allPortsFound) return;
@@ -3094,7 +3196,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
3094
3196
  this.root.db.toArray()
3095
3197
  );
3096
3198
  const [obstacles, errGettingObstacles] = tryNow(
3097
- () => getObstaclesFromSoup(this.root.db.toArray())
3199
+ () => getObstaclesFromSoup2(this.root.db.toArray())
3098
3200
  // Remove as any when autorouting-dataset gets updated
3099
3201
  );
3100
3202
  if (errGettingObstacles) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.134",
4
+ "version": "0.0.135",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",