@tscircuit/core 0.0.331 → 0.0.332

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +27 -10
  2. package/dist/index.js +516 -211
  3. package/package.json +3 -2
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _tscircuit_props from '@tscircuit/props';
2
- import { subcircuitGroupProps, traceProps, SupplierPartNumbers, SchematicPortArrangement, groupProps, AutorouterConfig, boardProps, capacitorProps, chipProps, diodeProps, jumperProps, ledProps, powerSourceProps, resistorProps, constraintProps, fabricationNotePathProps, fabricationNoteTextProps, footprintProps, subcircuitProps, holeProps, pcbKeepoutProps, netAliasProps, platedHoleProps, silkscreenCircleProps, silkscreenPathProps, silkscreenRectProps, silkscreenTextProps, silkscreenLineProps, smtPadProps, traceHintProps, viaProps, batteryProps, pinHeaderProps, resonatorProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, transistorProps, mosfetProps, switchProps, CapacitorProps, ChipProps, ResistorProps, ManualEditEvent, manual_edits_file } from '@tscircuit/props';
2
+ import { subcircuitGroupProps, AutorouterConfig, traceProps, SupplierPartNumbers, SchematicPortArrangement, groupProps, boardProps, capacitorProps, chipProps, diodeProps, jumperProps, ledProps, powerSourceProps, resistorProps, constraintProps, fabricationNotePathProps, fabricationNoteTextProps, footprintProps, subcircuitProps, holeProps, pcbKeepoutProps, netAliasProps, platedHoleProps, silkscreenCircleProps, silkscreenPathProps, silkscreenRectProps, silkscreenTextProps, silkscreenLineProps, smtPadProps, traceHintProps, viaProps, batteryProps, pinHeaderProps, resonatorProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, transistorProps, mosfetProps, switchProps, CapacitorProps, ChipProps, ResistorProps, ManualEditEvent, manual_edits_file } from '@tscircuit/props';
3
3
  import React, { ReactElement, DetailedHTMLProps, SVGProps } from 'react';
4
4
  export { createElement } from 'react';
5
5
  import * as zod from 'zod';
@@ -9,6 +9,7 @@ import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef,
9
9
  import { Matrix } from 'transformation-matrix';
10
10
  import { SoupUtilObjects } from '@tscircuit/soup-util';
11
11
  import * as _tscircuit_layout from '@tscircuit/layout';
12
+ import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
12
13
 
13
14
  declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InitializePortsFromChildren", "CreateNetsFromProps", "CreateTracesFromProps", "CreateTraceHintsFromProps", "SourceRender", "SourceParentAttachment", "PortMatching", "SourceTraceRender", "SourceAddConnectivityMapKey", "SchematicComponentRender", "SchematicPortRender", "SchematicLayout", "SchematicTraceRender", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbLayout", "PcbComponentSizeCalculation", "PcbBoardAutoSize", "PcbTraceRender", "PcbTraceHintRender", "PcbRouteNetIslands", "CadModelRender", "PartsEngineRender"];
14
15
  type RenderPhase = (typeof orderedRenderPhases)[number];
@@ -103,7 +104,7 @@ interface SchematicBoxDimensions {
103
104
  };
104
105
  }
105
106
 
106
- type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError";
107
+ type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError" | "autorouting:start" | "autorouting:end" | "autorouting:progress";
107
108
  declare class RootCircuit {
108
109
  firstChild: PrimitiveComponent | null;
109
110
  children: PrimitiveComponent[];
@@ -169,6 +170,7 @@ declare const Circuit: typeof RootCircuit;
169
170
  interface ISubcircuit extends PrimitiveComponent {
170
171
  _shouldUseTraceByTraceRouting(): boolean;
171
172
  _parsedProps: z.infer<typeof subcircuitGroupProps>;
173
+ _getAutorouterConfig(): AutorouterConfig;
172
174
  subcircuit_id: string | null;
173
175
  }
174
176
 
@@ -391,6 +393,7 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
391
393
  };
392
394
  getPortSelector(): string;
393
395
  doInitialSourceRender(): void;
396
+ doInitialSourceParentAttachment(): void;
394
397
  /**
395
398
  * Get all ports connected to this net.
396
399
  *
@@ -412,6 +415,8 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
412
415
  * Sometimes this phase doesn't find any net islands if the autorouter did
413
416
  * a good job and connected the islands. In some sense this is a "backup"
414
417
  * routing phase for autorouters that don't care about connecting nets.
418
+ *
419
+ * This should only run if the autorouter is sequential-trace
415
420
  */
416
421
  doInitialPcbRouteNetIslands(): void;
417
422
  renderError(message: Parameters<typeof PrimitiveComponent.prototype.renderError>[0]): void;
@@ -903,6 +908,7 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
903
908
  type SimplifiedPcbTrace = {
904
909
  type: "pcb_trace";
905
910
  pcb_trace_id: string;
911
+ connection_name?: string;
906
912
  route: Array<{
907
913
  route_type: "wire";
908
914
  x: number;
@@ -966,12 +972,15 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
966
972
  doInitialSourceParentAttachment(): void;
967
973
  doInitialPcbComponentRender(): void;
968
974
  doInitialCreateTraceHintsFromProps(): void;
969
- _getSimpleRouteJsonFromPcbTraces(): SimpleRouteJson;
970
975
  doInitialSourceAddConnectivityMapKey(): void;
971
976
  _areChildSubcircuitsRouted(): boolean;
972
977
  _shouldRouteAsync(): boolean;
973
978
  _hasTracesToRoute(): boolean;
974
979
  _runEffectMakeHttpAutoroutingRequest(): Promise<void>;
980
+ /**
981
+ * Run local autorouting using the CapacityMeshAutorouter
982
+ */
983
+ _runLocalCapacityMeshAutorouting(): Promise<void>;
975
984
  _startAsyncAutorouting(): void;
976
985
  doInitialPcbTraceRender(): void;
977
986
  updatePcbTraceRender(): void;
@@ -10715,10 +10724,15 @@ declare const applyEditEventsToManualEditsFile: ({ circuitJson, editEvents, manu
10715
10724
  /**
10716
10725
  * This function can only be called in the PcbTraceRender phase or later
10717
10726
  */
10718
- declare const getSimpleRouteJsonFromCircuitJson: ({ circuitJson, minTraceWidth, }: {
10719
- circuitJson: AnyCircuitElement[];
10727
+ declare const getSimpleRouteJsonFromCircuitJson: ({ db, circuitJson, subcircuit_id, minTraceWidth, }: {
10728
+ db?: SoupUtilObjects;
10729
+ circuitJson?: AnyCircuitElement[];
10730
+ subcircuit_id?: string | null;
10720
10731
  minTraceWidth?: number;
10721
- }) => SimpleRouteJson;
10732
+ }) => {
10733
+ simpleRouteJson: SimpleRouteJson;
10734
+ connMap: ConnectivityMap;
10735
+ };
10722
10736
 
10723
10737
  type RenderEvent = {
10724
10738
  type: string;
@@ -10737,7 +10751,7 @@ declare const getPhaseTimingsFromRenderEvents: (renderEvents: RenderEvent[]) =>
10737
10751
  type Nums16 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16";
10738
10752
  type Nums40 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16" | "17" | "18" | "19" | "20" | "21" | "22" | "23" | "24" | "25" | "26" | "27" | "28" | "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36" | "37" | "38" | "39" | "40";
10739
10753
  type PinNumbers100 = "pin1" | "pin2" | "pin3" | "pin4" | "pin5" | "pin6" | "pin7" | "pin8" | "pin9" | "pin10" | "pin11" | "pin12" | "pin13" | "pin14" | "pin15" | "pin16" | "pin17" | "pin18" | "pin19" | "pin20" | "pin21" | "pin22" | "pin23" | "pin24" | "pin25" | "pin26" | "pin27" | "pin28" | "pin29" | "pin30" | "pin31" | "pin32" | "pin33" | "pin34" | "pin35" | "pin36" | "pin37" | "pin38" | "pin39" | "pin40" | "pin41" | "pin42" | "pin43" | "pin44" | "pin45" | "pin46" | "pin47" | "pin48" | "pin49" | "pin50" | "pin51" | "pin52" | "pin53" | "pin54" | "pin55" | "pin56" | "pin57" | "pin58" | "pin59" | "pin60" | "pin61" | "pin62" | "pin63" | "pin64" | "pin65" | "pin66" | "pin67" | "pin68" | "pin69" | "pin70" | "pin71" | "pin72" | "pin73" | "pin74" | "pin75" | "pin76" | "pin77" | "pin78" | "pin79" | "pin80" | "pin81" | "pin82" | "pin83" | "pin84" | "pin85" | "pin86" | "pin87" | "pin88" | "pin89" | "pin90" | "pin91" | "pin92" | "pin93" | "pin94" | "pin95" | "pin96" | "pin97" | "pin98" | "pin99" | "pin100";
10740
- type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "VCC" | "VDD" | "GND" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
10754
+ type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "PWR" | "VCC" | "VDD" | "GND" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
10741
10755
  type TransistorPinNames = "base" | "collector" | "emitter";
10742
10756
 
10743
10757
  type NonPolarizedSel = Record<`R${Nums40}`, {
@@ -10762,12 +10776,15 @@ type PolarizedSel = Record<`C${Nums40}` | `L${Nums40}` | `LED${Nums40}` | `D${Nu
10762
10776
  pos: string;
10763
10777
  neg: string;
10764
10778
  }>;
10779
+ type CommonNetNames = "VCC" | "GND" | "VDD" | "PWR" | "V5" | "V3_3";
10765
10780
  type TransistorSel = Record<`Q${Nums40}`, Record<TransistorPinNames, string>>;
10766
- type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100, string>>;
10781
+ type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100 | CommonPinNames, string>>;
10767
10782
  type ChipSel = Record<`U${Nums40}`, Record<CommonPinNames, string>>;
10768
- type NetSel = Record<"net", Record<"VCC" | "GND" | "VDD", string>>;
10783
+ type NetSel = Record<"net", Record<CommonNetNames, string>>;
10769
10784
  type ConnectionSel = Record<`CN${Nums40}`, Record<CommonPinNames, string>>;
10770
- type Sel = NonPolarizedSel & PolarizedSel & TransistorSel & JumperSel & ChipSel & SwSel & NetSel & ConnectionSel;
10785
+ type SubcircuitSel = Record<"subcircuit", Record<`S${Nums40}`, SelWithoutSubcircuit>>;
10786
+ type SelWithoutSubcircuit = NonPolarizedSel & PolarizedSel & TransistorSel & JumperSel & ChipSel & SwSel & NetSel & ConnectionSel;
10787
+ type Sel = SubcircuitSel & SelWithoutSubcircuit;
10771
10788
  declare const sel: Sel;
10772
10789
 
10773
10790
  interface TscircuitElements {
package/dist/index.js CHANGED
@@ -1192,6 +1192,14 @@ var Net = class extends PrimitiveComponent {
1192
1192
  });
1193
1193
  this.source_net_id = net.source_net_id;
1194
1194
  }
1195
+ doInitialSourceParentAttachment() {
1196
+ const subcircuit = this.getSubcircuit();
1197
+ if (!subcircuit) return;
1198
+ const { db } = this.root;
1199
+ db.source_net.update(this.source_net_id, {
1200
+ subcircuit_id: subcircuit.subcircuit_id
1201
+ });
1202
+ }
1195
1203
  /**
1196
1204
  * Get all ports connected to this net.
1197
1205
  *
@@ -1235,10 +1243,14 @@ var Net = class extends PrimitiveComponent {
1235
1243
  * Sometimes this phase doesn't find any net islands if the autorouter did
1236
1244
  * a good job and connected the islands. In some sense this is a "backup"
1237
1245
  * routing phase for autorouters that don't care about connecting nets.
1246
+ *
1247
+ * This should only run if the autorouter is sequential-trace
1238
1248
  */
1239
1249
  doInitialPcbRouteNetIslands() {
1240
1250
  if (this.root?.pcbDisabled) return;
1241
1251
  if (this.getSubcircuit()._parsedProps.routingDisabled) return;
1252
+ if (this.getSubcircuit()._getAutorouterConfig().groupMode !== "sequential-trace")
1253
+ return;
1242
1254
  const { db } = this.root;
1243
1255
  const { _parsedProps: props } = this;
1244
1256
  const traces = this._getAllDirectlyConnectedTraces().filter(
@@ -1335,8 +1347,12 @@ var Net = class extends PrimitiveComponent {
1335
1347
  var createNetsFromProps = (component, props) => {
1336
1348
  for (const prop of props) {
1337
1349
  if (typeof prop === "string" && prop.startsWith("net.")) {
1338
- if (!component.getSubcircuit().selectOne(prop)) {
1339
- component.getSubcircuit().add(new Net({ name: prop.split("net.")[1] }));
1350
+ const subcircuit = component.getSubcircuit();
1351
+ if (!subcircuit.selectOne(prop)) {
1352
+ const net = new Net({
1353
+ name: prop.split("net.")[1]
1354
+ });
1355
+ subcircuit.add(net);
1340
1356
  }
1341
1357
  }
1342
1358
  }
@@ -2284,7 +2300,8 @@ var Port = class extends PrimitiveComponent {
2284
2300
  );
2285
2301
  }
2286
2302
  db.source_port.update(this.source_port_id, {
2287
- source_component_id: this.parent?.source_component_id
2303
+ source_component_id: this.parent?.source_component_id,
2304
+ subcircuit_id: this.getSubcircuit()?.subcircuit_id
2288
2305
  });
2289
2306
  this.source_component_id = this.parent?.source_component_id;
2290
2307
  }
@@ -2967,6 +2984,7 @@ var DirectLineRouter = class {
2967
2984
  const trace = {
2968
2985
  type: "pcb_trace",
2969
2986
  pcb_trace_id: "",
2987
+ connection_name: connection.name,
2970
2988
  route: [
2971
2989
  {
2972
2990
  route_type: "wire",
@@ -4689,7 +4707,6 @@ var NormalComponent = class extends PrimitiveComponent {
4689
4707
  if (symbol) {
4690
4708
  const schematic_component2 = db.schematic_component.insert({
4691
4709
  center,
4692
- rotation: props.schRotation ?? 0,
4693
4710
  size: symbol.size,
4694
4711
  source_component_id: this.source_component_id,
4695
4712
  symbol_name,
@@ -5133,64 +5150,156 @@ import {
5133
5150
  groupProps
5134
5151
  } from "@tscircuit/props";
5135
5152
  import * as SAL from "@tscircuit/schematic-autolayout";
5136
- import "circuit-json";
5137
- import { ConnectivityMap } from "circuit-json-to-connectivity-map";
5138
- import Debug5 from "debug";
5139
5153
 
5140
- // lib/utils/autorouting/getSimpleRouteJsonFromTracesAndDb.ts
5141
- import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
5142
- var getSimpleRouteJsonFromTracesAndDb = ({
5143
- db,
5144
- traces,
5145
- minTraceWidth = 0.1
5146
- }) => {
5147
- const obstacles = getObstaclesFromSoup2([
5148
- ...db.pcb_component.list(),
5149
- ...db.pcb_smtpad.list(),
5150
- ...db.pcb_plated_hole.list()
5151
- ]);
5152
- const allPoints = obstacles.flatMap((o) => [
5153
- {
5154
- x: o.center.x - o.width / 2,
5155
- y: o.center.y - o.height / 2
5156
- },
5157
- {
5158
- x: o.center.x + o.width / 2,
5159
- y: o.center.y + o.height / 2
5160
- }
5161
- ]);
5162
- const bounds = {
5163
- minX: Math.min(...allPoints.map((p) => p.x)) - 1,
5164
- maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
5165
- minY: Math.min(...allPoints.map((p) => p.y)) - 1,
5166
- maxY: Math.max(...allPoints.map((p) => p.y)) + 1
5167
- };
5168
- const connections = traces.map((trace) => {
5169
- const connectedPorts = trace._findConnectedPorts();
5170
- if (!connectedPorts.allPortsFound || connectedPorts.ports.length < 2)
5171
- return null;
5172
- return {
5173
- name: trace.source_trace_id ?? "",
5174
- pointsToConnect: connectedPorts.ports.map((port) => {
5175
- const pos = port._getGlobalPcbPositionBeforeLayout();
5176
- return {
5177
- x: pos.x,
5178
- y: pos.y,
5179
- layer: port.getAvailablePcbLayers()[0] ?? "top"
5180
- };
5181
- })
5182
- };
5183
- }).filter((c) => c !== null);
5184
- return {
5185
- bounds,
5186
- obstacles: [],
5187
- connections,
5188
- layerCount: 2,
5189
- minTraceWidth
5154
+ // lib/utils/autorouting/CapacityMeshAutorouter.ts
5155
+ import { CapacityMeshSolver } from "@tscircuit/capacity-autorouter";
5156
+ var CapacityMeshAutorouter = class {
5157
+ input;
5158
+ isRouting = false;
5159
+ solver;
5160
+ eventHandlers = {
5161
+ complete: [],
5162
+ error: [],
5163
+ progress: []
5190
5164
  };
5165
+ cycleCount = 0;
5166
+ stepDelay;
5167
+ timeoutId;
5168
+ constructor(input, options = {}) {
5169
+ this.input = input;
5170
+ const { capacityDepth, targetMinCapacity, stepDelay = 0 } = options;
5171
+ this.solver = new CapacityMeshSolver(input, {
5172
+ capacityDepth,
5173
+ targetMinCapacity
5174
+ });
5175
+ this.stepDelay = stepDelay;
5176
+ }
5177
+ /**
5178
+ * Start the autorouting process asynchronously
5179
+ * This will emit progress events during routing and a complete event when done
5180
+ */
5181
+ start() {
5182
+ if (this.isRouting) return;
5183
+ this.isRouting = true;
5184
+ this.cycleCount = 0;
5185
+ this.runCycleAndQueueNextCycle();
5186
+ }
5187
+ /**
5188
+ * Execute the next routing step and schedule the following one if needed
5189
+ */
5190
+ runCycleAndQueueNextCycle() {
5191
+ if (!this.isRouting) return;
5192
+ try {
5193
+ if (this.solver.solved || this.solver.failed) {
5194
+ if (this.solver.failed) {
5195
+ this.emitEvent({
5196
+ type: "error",
5197
+ error: new Error(this.solver.error || "Routing failed")
5198
+ });
5199
+ } else {
5200
+ this.emitEvent({
5201
+ type: "complete",
5202
+ traces: this.solver.getOutputSimpleRouteJson().traces || []
5203
+ });
5204
+ }
5205
+ this.isRouting = false;
5206
+ return;
5207
+ }
5208
+ const startTime = performance.now();
5209
+ const startIterations = this.solver.iterations;
5210
+ while (performance.now() - startTime < 10 && !this.solver.failed && !this.solver.solved) {
5211
+ this.solver.step();
5212
+ }
5213
+ this.cycleCount++;
5214
+ const debugGraphics = this.solver.activeSolver?.visualize() || void 0;
5215
+ const progress = this.solver.progress;
5216
+ this.emitEvent({
5217
+ type: "progress",
5218
+ steps: this.cycleCount,
5219
+ progress,
5220
+ phase: this.solver.getCurrentPhase(),
5221
+ debugGraphics
5222
+ });
5223
+ if (this.stepDelay > 0) {
5224
+ this.timeoutId = setTimeout(
5225
+ () => this.runCycleAndQueueNextCycle(),
5226
+ this.stepDelay
5227
+ );
5228
+ } else {
5229
+ this.timeoutId = setTimeout(
5230
+ () => this.runCycleAndQueueNextCycle(),
5231
+ 0
5232
+ );
5233
+ }
5234
+ } catch (error) {
5235
+ this.emitEvent({
5236
+ type: "error",
5237
+ error: error instanceof Error ? error : new Error(String(error))
5238
+ });
5239
+ this.isRouting = false;
5240
+ }
5241
+ }
5242
+ /**
5243
+ * Stop the routing process if it's in progress
5244
+ */
5245
+ stop() {
5246
+ if (!this.isRouting) return;
5247
+ this.isRouting = false;
5248
+ if (this.timeoutId !== void 0) {
5249
+ clearTimeout(this.timeoutId);
5250
+ this.timeoutId = void 0;
5251
+ }
5252
+ }
5253
+ on(event, callback) {
5254
+ if (event === "complete") {
5255
+ this.eventHandlers.complete.push(
5256
+ callback
5257
+ );
5258
+ } else if (event === "error") {
5259
+ this.eventHandlers.error.push(
5260
+ callback
5261
+ );
5262
+ } else if (event === "progress") {
5263
+ this.eventHandlers.progress.push(
5264
+ callback
5265
+ );
5266
+ }
5267
+ }
5268
+ /**
5269
+ * Emit an event to all registered handlers
5270
+ */
5271
+ emitEvent(event) {
5272
+ if (event.type === "complete") {
5273
+ for (const handler of this.eventHandlers.complete) {
5274
+ handler(event);
5275
+ }
5276
+ } else if (event.type === "error") {
5277
+ for (const handler of this.eventHandlers.error) {
5278
+ handler(event);
5279
+ }
5280
+ } else if (event.type === "progress") {
5281
+ for (const handler of this.eventHandlers.progress) {
5282
+ handler(event);
5283
+ }
5284
+ }
5285
+ }
5286
+ /**
5287
+ * Solve the routing problem synchronously
5288
+ * @returns Array of routed traces
5289
+ */
5290
+ solveSync() {
5291
+ this.solver.solve();
5292
+ if (this.solver.failed) {
5293
+ throw new Error(this.solver.error || "Routing failed");
5294
+ }
5295
+ return this.solver.getOutputSimpleRouteJson().traces || [];
5296
+ }
5191
5297
  };
5192
5298
 
5193
5299
  // lib/components/primitive-components/Group/Group.ts
5300
+ import "circuit-json";
5301
+ import { ConnectivityMap as ConnectivityMap2 } from "circuit-json-to-connectivity-map";
5302
+ import Debug5 from "debug";
5194
5303
  import "zod";
5195
5304
 
5196
5305
  // lib/components/primitive-components/TraceHint.ts
@@ -5254,6 +5363,220 @@ var TraceHint = class extends PrimitiveComponent {
5254
5363
  }
5255
5364
  };
5256
5365
 
5366
+ // lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
5367
+ import "zod";
5368
+ import { su } from "@tscircuit/soup-util";
5369
+ var applyEditEventsToManualEditsFile = ({
5370
+ circuitJson,
5371
+ editEvents,
5372
+ manualEditsFile
5373
+ }) => {
5374
+ const updatedManualEditsFile = {
5375
+ ...manualEditsFile,
5376
+ schematic_placements: [...manualEditsFile.schematic_placements ?? []]
5377
+ };
5378
+ for (const editEvent of editEvents) {
5379
+ if (editEvent.edit_event_type === "edit_schematic_component_location") {
5380
+ const { schematic_component_id, new_center } = editEvent;
5381
+ const schematic_component2 = su(circuitJson).schematic_component.get(
5382
+ schematic_component_id
5383
+ );
5384
+ if (!schematic_component2) continue;
5385
+ const source_component = su(circuitJson).source_component.get(
5386
+ schematic_component2.source_component_id
5387
+ );
5388
+ if (!source_component) continue;
5389
+ const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
5390
+ (p) => p.selector === source_component.name
5391
+ );
5392
+ const newPlacement = {
5393
+ selector: source_component.name,
5394
+ center: new_center,
5395
+ relative_to: "group_center"
5396
+ };
5397
+ if (existingPlacementIndex >= 0) {
5398
+ updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
5399
+ } else {
5400
+ updatedManualEditsFile.schematic_placements.push(newPlacement);
5401
+ }
5402
+ }
5403
+ }
5404
+ return updatedManualEditsFile;
5405
+ };
5406
+
5407
+ // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
5408
+ import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
5409
+ import { su as su2 } from "@tscircuit/soup-util";
5410
+ import {
5411
+ getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
5412
+ } from "circuit-json-to-connectivity-map";
5413
+
5414
+ // lib/utils/autorouting/getAncestorSubcircuitIds.ts
5415
+ var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
5416
+ const groups = db.source_group.list();
5417
+ const result = [];
5418
+ const findDescendants = (parentId) => {
5419
+ const children = groups.filter(
5420
+ (group) => group.parent_subcircuit_id === parentId
5421
+ );
5422
+ for (const child of children) {
5423
+ if (child.subcircuit_id) {
5424
+ result.push(child.subcircuit_id);
5425
+ findDescendants(child.subcircuit_id);
5426
+ }
5427
+ }
5428
+ };
5429
+ findDescendants(root_subcircuit_id);
5430
+ return result;
5431
+ };
5432
+
5433
+ // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
5434
+ var getSimpleRouteJsonFromCircuitJson = ({
5435
+ db,
5436
+ circuitJson,
5437
+ subcircuit_id,
5438
+ minTraceWidth = 0.1
5439
+ }) => {
5440
+ if (!db && circuitJson) {
5441
+ db = su2(circuitJson);
5442
+ }
5443
+ if (!db) {
5444
+ throw new Error("db or circuitJson is required");
5445
+ }
5446
+ const relevantSubcircuitIds = subcircuit_id ? /* @__PURE__ */ new Set([subcircuit_id]) : null;
5447
+ if (subcircuit_id) {
5448
+ const descendantSubcircuitIds = getDescendantSubcircuitIds(
5449
+ db,
5450
+ subcircuit_id
5451
+ );
5452
+ for (const id of descendantSubcircuitIds) {
5453
+ relevantSubcircuitIds.add(id);
5454
+ }
5455
+ }
5456
+ const subcircuitElements = (circuitJson ?? db.toArray()).filter(
5457
+ (e) => !subcircuit_id || "subcircuit_id" in e && relevantSubcircuitIds.has(e.subcircuit_id)
5458
+ );
5459
+ const board = db.pcb_board.list()[0];
5460
+ db = su2(subcircuitElements);
5461
+ const connMap = getFullConnectivityMapFromCircuitJson2(subcircuitElements);
5462
+ const obstacles = getObstaclesFromSoup2(
5463
+ [
5464
+ ...db.pcb_component.list(),
5465
+ ...db.pcb_smtpad.list(),
5466
+ ...db.pcb_plated_hole.list()
5467
+ ].filter(
5468
+ (e) => !subcircuit_id || relevantSubcircuitIds?.has(e.subcircuit_id)
5469
+ ),
5470
+ connMap
5471
+ );
5472
+ const allPoints = obstacles.flatMap((o) => [
5473
+ {
5474
+ x: o.center.x - o.width / 2,
5475
+ y: o.center.y - o.height / 2
5476
+ },
5477
+ {
5478
+ x: o.center.x + o.width / 2,
5479
+ y: o.center.y + o.height / 2
5480
+ }
5481
+ ]);
5482
+ let bounds;
5483
+ if (board) {
5484
+ bounds = {
5485
+ minX: board.center.x - board.width / 2,
5486
+ maxX: board.center.x + board.width / 2,
5487
+ minY: board.center.y - board.height / 2,
5488
+ maxY: board.center.y + board.height / 2
5489
+ };
5490
+ } else {
5491
+ bounds = {
5492
+ minX: Math.min(...allPoints.map((p) => p.x)) - 1,
5493
+ maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
5494
+ minY: Math.min(...allPoints.map((p) => p.y)) - 1,
5495
+ maxY: Math.max(...allPoints.map((p) => p.y)) + 1
5496
+ };
5497
+ }
5498
+ const directTraceConnections = db.source_trace.list().map((trace) => {
5499
+ const connectedPorts = trace.connected_source_port_ids.map((id) => {
5500
+ const source_port = db.source_port.get(id);
5501
+ const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
5502
+ return {
5503
+ ...source_port,
5504
+ ...pcb_port
5505
+ };
5506
+ });
5507
+ if (connectedPorts.length < 2) return null;
5508
+ return {
5509
+ name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
5510
+ source_trace_id: trace.source_trace_id,
5511
+ pointsToConnect: connectedPorts.map((port) => {
5512
+ return {
5513
+ x: port.x,
5514
+ y: port.y,
5515
+ layer: port.layers?.[0] ?? "top"
5516
+ };
5517
+ })
5518
+ };
5519
+ }).filter((c) => c !== null);
5520
+ const source_nets = db.source_net.list().filter(
5521
+ (e) => !subcircuit_id || relevantSubcircuitIds?.has(e.subcircuit_id)
5522
+ );
5523
+ const connectionsFromNets = [];
5524
+ for (const net of source_nets) {
5525
+ const connectedSourceTraces = db.source_trace.list().filter((st) => st.connected_source_net_ids?.includes(net.source_net_id));
5526
+ connectionsFromNets.push({
5527
+ name: connMap.getNetConnectedToId(net.source_net_id) ?? net.source_net_id,
5528
+ pointsToConnect: connectedSourceTraces.flatMap((st) => {
5529
+ const pcb_ports = db.pcb_port.list().filter(
5530
+ (p) => st.connected_source_port_ids.includes(p.source_port_id)
5531
+ );
5532
+ return pcb_ports.map((p) => ({
5533
+ x: p.x,
5534
+ y: p.y,
5535
+ layer: p.layers?.[0] ?? "top",
5536
+ pcb_port_id: p.pcb_port_id
5537
+ }));
5538
+ })
5539
+ });
5540
+ }
5541
+ return {
5542
+ simpleRouteJson: {
5543
+ bounds,
5544
+ obstacles,
5545
+ connections: [...directTraceConnections, ...connectionsFromNets],
5546
+ // TODO add traces so that we don't run into things routed by another
5547
+ // subcircuit
5548
+ layerCount: 2,
5549
+ minTraceWidth
5550
+ },
5551
+ connMap
5552
+ };
5553
+ };
5554
+
5555
+ // lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
5556
+ var getPhaseTimingsFromRenderEvents = (renderEvents) => {
5557
+ const phaseTimings = {};
5558
+ if (!renderEvents) return phaseTimings;
5559
+ for (const renderPhase of orderedRenderPhases) {
5560
+ phaseTimings[renderPhase] = 0;
5561
+ }
5562
+ const startEvents = /* @__PURE__ */ new Map();
5563
+ for (const event of renderEvents) {
5564
+ const [, , phase, eventType] = event.type.split(":");
5565
+ if (eventType === "start") {
5566
+ startEvents.set(`${phase}:${event.renderId}`, event);
5567
+ continue;
5568
+ }
5569
+ if (eventType === "end") {
5570
+ const startEvent = startEvents.get(`${phase}:${event.renderId}`);
5571
+ if (startEvent) {
5572
+ const duration = event.createdAt - startEvent.createdAt;
5573
+ phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
5574
+ }
5575
+ }
5576
+ }
5577
+ return phaseTimings;
5578
+ };
5579
+
5257
5580
  // lib/components/primitive-components/Group/Group.ts
5258
5581
  var Group = class extends NormalComponent {
5259
5582
  pcb_group_id = null;
@@ -5319,20 +5642,11 @@ var Group = class extends NormalComponent {
5319
5642
  );
5320
5643
  }
5321
5644
  }
5322
- _getSimpleRouteJsonFromPcbTraces() {
5323
- const traces = this.selectAll("trace");
5324
- const { db } = this.root;
5325
- return getSimpleRouteJsonFromTracesAndDb({
5326
- db,
5327
- traces,
5328
- minTraceWidth: this._parsedProps.minTraceWidth ?? 0.1
5329
- });
5330
- }
5331
5645
  doInitialSourceAddConnectivityMapKey() {
5332
5646
  if (!this.isSubcircuit) return;
5333
5647
  const { db } = this.root;
5334
5648
  const traces = this.selectAll("trace");
5335
- const connMap = new ConnectivityMap({});
5649
+ const connMap = new ConnectivityMap2({});
5336
5650
  connMap.addConnections(
5337
5651
  traces.map((t) => {
5338
5652
  const source_trace = db.source_trace.get(
@@ -5370,9 +5684,10 @@ var Group = class extends NormalComponent {
5370
5684
  }
5371
5685
  _shouldRouteAsync() {
5372
5686
  const autorouter = this._getAutorouterConfig();
5373
- if (autorouter.local) return false;
5374
5687
  if (autorouter.groupMode === "sequential-trace") return false;
5375
- return true;
5688
+ if (autorouter.local && autorouter.groupMode === "subcircuit") return true;
5689
+ if (!autorouter.local) return true;
5690
+ return false;
5376
5691
  }
5377
5692
  _hasTracesToRoute() {
5378
5693
  const debug4 = Debug5("tscircuit:core:_hasTracesToRoute");
@@ -5403,7 +5718,11 @@ var Group = class extends NormalComponent {
5403
5718
  {
5404
5719
  method: "POST",
5405
5720
  body: JSON.stringify({
5406
- input_simple_route_json: this._getSimpleRouteJsonFromPcbTraces(),
5721
+ input_simple_route_json: getSimpleRouteJsonFromCircuitJson({
5722
+ db,
5723
+ minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
5724
+ subcircuit_id: this.subcircuit_id
5725
+ }).simpleRouteJson,
5407
5726
  subcircuit_id: this.subcircuit_id
5408
5727
  }),
5409
5728
  headers: { "Content-Type": "application/json" }
@@ -5481,12 +5800,73 @@ var Group = class extends NormalComponent {
5481
5800
  await new Promise((resolve) => setTimeout(resolve, 100));
5482
5801
  }
5483
5802
  }
5803
+ /**
5804
+ * Run local autorouting using the CapacityMeshAutorouter
5805
+ */
5806
+ async _runLocalCapacityMeshAutorouting() {
5807
+ const { db } = this.root;
5808
+ const debug4 = Debug5("tscircuit:core:_runLocalCapacityMeshAutorouting");
5809
+ debug4(`[${this.getString()}] starting local capacity mesh autorouting`);
5810
+ const { simpleRouteJson, connMap } = getSimpleRouteJsonFromCircuitJson({
5811
+ db,
5812
+ minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
5813
+ subcircuit_id: this.subcircuit_id
5814
+ });
5815
+ this.root?.emit("autorouting:start", {
5816
+ subcircuit_id: this.subcircuit_id,
5817
+ componentDisplayName: this.getString(),
5818
+ simpleRouteJson
5819
+ });
5820
+ const autorouter = new CapacityMeshAutorouter(simpleRouteJson, {
5821
+ // Optional configuration parameters
5822
+ capacityDepth: this.props.autorouter?.capacityDepth,
5823
+ targetMinCapacity: this.props.autorouter?.targetMinCapacity
5824
+ });
5825
+ const routingPromise = new Promise(
5826
+ (resolve, reject) => {
5827
+ autorouter.on("complete", (event) => {
5828
+ debug4(`[${this.getString()}] local autorouting complete`);
5829
+ resolve(event.traces);
5830
+ });
5831
+ autorouter.on("error", (event) => {
5832
+ debug4(
5833
+ `[${this.getString()}] local autorouting error: ${event.error.message}`
5834
+ );
5835
+ reject(event.error);
5836
+ });
5837
+ }
5838
+ );
5839
+ autorouter.start();
5840
+ try {
5841
+ const traces = await routingPromise;
5842
+ this._asyncAutoroutingResult = {
5843
+ output_pcb_traces: traces
5844
+ };
5845
+ this._markDirty("PcbTraceRender");
5846
+ } catch (error) {
5847
+ const { db: db2 } = this.root;
5848
+ db2.pcb_autorouting_error.insert({
5849
+ pcb_error_id: `local_${this.subcircuit_id}`,
5850
+ message: error instanceof Error ? error.message : String(error)
5851
+ });
5852
+ throw error;
5853
+ } finally {
5854
+ autorouter.stop();
5855
+ }
5856
+ }
5484
5857
  _startAsyncAutorouting() {
5485
5858
  this._hasStartedAsyncAutorouting = true;
5486
- this._queueAsyncEffect(
5487
- "make-http-autorouting-request",
5488
- async () => this._runEffectMakeHttpAutoroutingRequest()
5489
- );
5859
+ if (this._getAutorouterConfig().local) {
5860
+ this._queueAsyncEffect(
5861
+ "capacity-mesh-autorouting",
5862
+ async () => this._runLocalCapacityMeshAutorouting()
5863
+ );
5864
+ } else {
5865
+ this._queueAsyncEffect(
5866
+ "make-http-autorouting-request",
5867
+ async () => this._runEffectMakeHttpAutoroutingRequest()
5868
+ );
5869
+ }
5490
5870
  }
5491
5871
  doInitialPcbTraceRender() {
5492
5872
  const debug4 = Debug5("tscircuit:core:doInitialPcbTraceRender");
@@ -5508,6 +5888,7 @@ var Group = class extends NormalComponent {
5508
5888
  }
5509
5889
  updatePcbTraceRender() {
5510
5890
  const debug4 = Debug5("tscircuit:core:updatePcbTraceRender");
5891
+ debug4(`[${this.getString()}] updating...`);
5511
5892
  if (!this.isSubcircuit) return;
5512
5893
  if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
5513
5894
  if (this._areChildSubcircuitsRouted()) {
@@ -5522,10 +5903,16 @@ var Group = class extends NormalComponent {
5522
5903
  if (this._shouldUseTraceByTraceRouting()) return;
5523
5904
  const { db } = this.root;
5524
5905
  if (this._asyncAutoroutingResult.output_simple_route_json) {
5906
+ debug4(
5907
+ `[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`
5908
+ );
5525
5909
  this._updatePcbTraceRenderFromSimpleRouteJson();
5526
5910
  return;
5527
5911
  }
5528
5912
  if (this._asyncAutoroutingResult.output_pcb_traces) {
5913
+ debug4(
5914
+ `[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`
5915
+ );
5529
5916
  this._updatePcbTraceRenderFromPcbTraces();
5530
5917
  return;
5531
5918
  }
@@ -5534,9 +5921,9 @@ var Group = class extends NormalComponent {
5534
5921
  const { db } = this.root;
5535
5922
  const { traces: routedTraces } = this._asyncAutoroutingResult.output_simple_route_json;
5536
5923
  if (!routedTraces) return;
5537
- const circuitTraces = this.selectAll("trace");
5538
5924
  for (const routedTrace of routedTraces) {
5539
5925
  const pcb_trace = db.pcb_trace.insert({
5926
+ subcircuit_id: this.subcircuit_id,
5540
5927
  route: routedTrace.route
5541
5928
  // source_trace_id: circuitTrace.source_trace_id!,
5542
5929
  });
@@ -5550,6 +5937,22 @@ var Group = class extends NormalComponent {
5550
5937
  pcb_trace.subcircuit_id = this.subcircuit_id;
5551
5938
  db.pcb_trace.insert(pcb_trace);
5552
5939
  }
5940
+ for (const pcb_trace of output_pcb_traces) {
5941
+ for (const point of pcb_trace.route) {
5942
+ if (point.route_type === "via") {
5943
+ db.pcb_via.insert({
5944
+ pcb_trace_id: pcb_trace.pcb_trace_id,
5945
+ x: point.x,
5946
+ y: point.y,
5947
+ hole_diameter: 0.3,
5948
+ outer_diameter: 0.6,
5949
+ layers: [point.from_layer, point.to_layer],
5950
+ from_layer: point.from_layer,
5951
+ to_layer: point.to_layer
5952
+ });
5953
+ }
5954
+ }
5955
+ }
5553
5956
  }
5554
5957
  doInitialSchematicLayout() {
5555
5958
  if (!this.isSubcircuit) return;
@@ -5581,7 +5984,7 @@ var Group = class extends NormalComponent {
5581
5984
  const defaults = {
5582
5985
  serverUrl: "https://registry-api.tscircuit.com",
5583
5986
  serverMode: "job",
5584
- serverCacheEnabled: false
5987
+ serverCacheEnabled: true
5585
5988
  };
5586
5989
  const autorouter = this._parsedProps.autorouter ?? this.getInheritedProperty("autorouter");
5587
5990
  if (typeof autorouter === "object") {
@@ -5593,13 +5996,27 @@ var Group = class extends NormalComponent {
5593
5996
  }
5594
5997
  if (autorouter === "auto-local")
5595
5998
  return {
5596
- local: true
5999
+ local: true,
6000
+ groupMode: "subcircuit"
5597
6001
  };
5598
6002
  if (autorouter === "sequential-trace")
5599
6003
  return {
5600
6004
  local: true,
5601
6005
  groupMode: "sequential-trace"
5602
6006
  };
6007
+ if (autorouter === "subcircuit")
6008
+ return {
6009
+ local: true,
6010
+ groupMode: "subcircuit"
6011
+ };
6012
+ if (autorouter === "auto-cloud")
6013
+ return {
6014
+ local: false,
6015
+ groupMode: "subcircuit",
6016
+ serverUrl: defaults.serverUrl,
6017
+ serverMode: defaults.serverMode,
6018
+ serverCacheEnabled: true
6019
+ };
5603
6020
  return {
5604
6021
  local: true,
5605
6022
  groupMode: "sequential-trace"
@@ -6457,7 +6874,9 @@ var PinHeader = class extends NormalComponent {
6457
6874
  new Port({
6458
6875
  name: `pin${i}`,
6459
6876
  pinNumber: i,
6460
- aliases: []
6877
+ aliases: [this._parsedProps.pinLabels?.[i - 1]].filter(
6878
+ Boolean
6879
+ )
6461
6880
  })
6462
6881
  );
6463
6882
  }
@@ -6778,7 +7197,7 @@ var Switch = class extends NormalComponent {
6778
7197
  };
6779
7198
 
6780
7199
  // lib/RootCircuit.ts
6781
- import { su } from "@tscircuit/soup-util";
7200
+ import { su as su3 } from "@tscircuit/soup-util";
6782
7201
  import { isValidElement as isValidElement2 } from "react";
6783
7202
  import { identity as identity4 } from "transformation-matrix";
6784
7203
  var RootCircuit = class {
@@ -6799,7 +7218,7 @@ var RootCircuit = class {
6799
7218
  _hasRenderedAtleastOnce = false;
6800
7219
  constructor() {
6801
7220
  this.children = [];
6802
- this.db = su([]);
7221
+ this.db = su3([]);
6803
7222
  this.root = this;
6804
7223
  }
6805
7224
  add(componentOrElm) {
@@ -7043,137 +7462,6 @@ var useResistor = createUseComponent(
7043
7462
  resistorPins2
7044
7463
  );
7045
7464
 
7046
- // lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
7047
- import "zod";
7048
- import { su as su2 } from "@tscircuit/soup-util";
7049
- var applyEditEventsToManualEditsFile = ({
7050
- circuitJson,
7051
- editEvents,
7052
- manualEditsFile
7053
- }) => {
7054
- const updatedManualEditsFile = {
7055
- ...manualEditsFile,
7056
- schematic_placements: [...manualEditsFile.schematic_placements ?? []]
7057
- };
7058
- for (const editEvent of editEvents) {
7059
- if (editEvent.edit_event_type === "edit_schematic_component_location") {
7060
- const { schematic_component_id, new_center } = editEvent;
7061
- const schematic_component2 = su2(circuitJson).schematic_component.get(
7062
- schematic_component_id
7063
- );
7064
- if (!schematic_component2) continue;
7065
- const source_component = su2(circuitJson).source_component.get(
7066
- schematic_component2.source_component_id
7067
- );
7068
- if (!source_component) continue;
7069
- const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
7070
- (p) => p.selector === source_component.name
7071
- );
7072
- const newPlacement = {
7073
- selector: source_component.name,
7074
- center: new_center,
7075
- relative_to: "group_center"
7076
- };
7077
- if (existingPlacementIndex >= 0) {
7078
- updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
7079
- } else {
7080
- updatedManualEditsFile.schematic_placements.push(newPlacement);
7081
- }
7082
- }
7083
- }
7084
- return updatedManualEditsFile;
7085
- };
7086
-
7087
- // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
7088
- import { getObstaclesFromSoup as getObstaclesFromSoup3 } from "@tscircuit/infgrid-ijump-astar";
7089
- import { su as su3 } from "@tscircuit/soup-util";
7090
- import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2 } from "circuit-json-to-connectivity-map";
7091
- var getSimpleRouteJsonFromCircuitJson = ({
7092
- circuitJson,
7093
- minTraceWidth = 0.1
7094
- }) => {
7095
- const db = su3(circuitJson);
7096
- const connMap = getFullConnectivityMapFromCircuitJson2(circuitJson);
7097
- const obstacles = getObstaclesFromSoup3(
7098
- [
7099
- ...db.pcb_component.list(),
7100
- ...db.pcb_smtpad.list(),
7101
- ...db.pcb_plated_hole.list()
7102
- ],
7103
- connMap
7104
- );
7105
- const allPoints = obstacles.flatMap((o) => [
7106
- {
7107
- x: o.center.x - o.width / 2,
7108
- y: o.center.y - o.height / 2
7109
- },
7110
- {
7111
- x: o.center.x + o.width / 2,
7112
- y: o.center.y + o.height / 2
7113
- }
7114
- ]);
7115
- const bounds = {
7116
- minX: Math.min(...allPoints.map((p) => p.x)) - 1,
7117
- maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
7118
- minY: Math.min(...allPoints.map((p) => p.y)) - 1,
7119
- maxY: Math.max(...allPoints.map((p) => p.y)) + 1
7120
- };
7121
- const connections = db.source_trace.list().map((trace) => {
7122
- const connectedPorts = trace.connected_source_port_ids.map((id) => {
7123
- const source_port = db.source_port.get(id);
7124
- const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
7125
- return {
7126
- ...source_port,
7127
- ...pcb_port
7128
- };
7129
- });
7130
- if (connectedPorts.length < 2) return null;
7131
- return {
7132
- name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
7133
- source_trace_id: trace.source_trace_id,
7134
- pointsToConnect: connectedPorts.map((port) => {
7135
- return {
7136
- x: port.x,
7137
- y: port.y,
7138
- layer: port.layers?.[0] ?? "top"
7139
- };
7140
- })
7141
- };
7142
- }).filter((c) => c !== null);
7143
- return {
7144
- bounds,
7145
- obstacles,
7146
- connections,
7147
- layerCount: 2,
7148
- minTraceWidth
7149
- };
7150
- };
7151
-
7152
- // lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
7153
- var getPhaseTimingsFromRenderEvents = (renderEvents) => {
7154
- const phaseTimings = {};
7155
- if (!renderEvents) return phaseTimings;
7156
- for (const renderPhase of orderedRenderPhases) {
7157
- phaseTimings[renderPhase] = 0;
7158
- }
7159
- const startEvents = /* @__PURE__ */ new Map();
7160
- for (const event of renderEvents) {
7161
- const [, , phase, eventType] = event.type.split(":");
7162
- if (eventType === "start") {
7163
- startEvents.set(`${phase}:${event.renderId}`, event);
7164
- continue;
7165
- }
7166
- if (eventType === "end") {
7167
- const startEvent = startEvents.get(`${phase}:${event.renderId}`);
7168
- if (startEvent) {
7169
- const duration = event.createdAt - startEvent.createdAt;
7170
- phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
7171
- }
7172
- }
7173
- }
7174
- return phaseTimings;
7175
- };
7176
-
7177
7465
  // lib/sel/sel.ts
7178
7466
  var sel = new Proxy(
7179
7467
  {},
@@ -7186,6 +7474,23 @@ var sel = new Proxy(
7186
7474
  if (prop1 === "net") {
7187
7475
  return `net.${prop2}`;
7188
7476
  }
7477
+ if (prop1 === "subcircuit") {
7478
+ return new Proxy(
7479
+ {},
7480
+ {
7481
+ get: (_3, prop3) => {
7482
+ return new Proxy(
7483
+ {},
7484
+ {
7485
+ get: (_4, prop4) => {
7486
+ return `subcircuit.${prop2} > .${prop3} > .${prop4}`;
7487
+ }
7488
+ }
7489
+ );
7490
+ }
7491
+ }
7492
+ );
7493
+ }
7189
7494
  return `.${prop1} > .${prop2}`;
7190
7495
  }
7191
7496
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.331",
4
+ "version": "0.0.332",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -53,12 +53,13 @@
53
53
  },
54
54
  "dependencies": {
55
55
  "@lume/kiwi": "^0.4.3",
56
+ "@tscircuit/capacity-autorouter": "^0.0.12",
56
57
  "@tscircuit/infgrid-ijump-astar": "^0.0.33",
57
58
  "@tscircuit/math-utils": "^0.0.9",
58
59
  "@tscircuit/props": "^0.0.152",
59
60
  "@tscircuit/schematic-autolayout": "^0.0.6",
60
61
  "@tscircuit/soup-util": "^0.0.41",
61
- "circuit-json": "^0.0.142",
62
+ "circuit-json": "^0.0.144",
62
63
  "circuit-json-to-connectivity-map": "^0.0.17",
63
64
  "format-si-unit": "^0.0.3",
64
65
  "nanoid": "^5.0.7",