@tscircuit/core 0.0.1901 → 0.0.1903

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
@@ -138,11 +138,13 @@ type SimplifiedPcbTrace = Omit<SimplifiedPcbTrace$1, "connection_name" | "route"
138
138
  };
139
139
  /** A connection identifier in Simple Route JSON. */
140
140
  type SrjConnectionName = string;
141
- type SimpleRoutePoint = {
141
+ /** Core emits fixed-layer routing terminals, not multilayer connection points. */
142
+ type SingleLayerConnectionPoint = {
142
143
  x: number;
143
144
  y: number;
144
145
  layer: string;
145
- layers?: string[];
146
+ /** Reject mixed layer/layers objects even when assigned through a variable. */
147
+ layers?: never;
146
148
  pointId?: string;
147
149
  pcb_port_id?: string;
148
150
  /** Stable semantic selector for the source port, e.g. `U1.USB_DM`. */
@@ -152,6 +154,8 @@ type SimpleRoutePoint = {
152
154
  viaDiameter?: number;
153
155
  };
154
156
  };
157
+ /** Backward-compatible name for core's single-layer routing terminals. */
158
+ type SimpleRoutePoint = SingleLayerConnectionPoint;
155
159
  type SimpleRouteConnection = {
156
160
  name: SrjConnectionName;
157
161
  routingPcbGroupId?: PcbGroupId;
@@ -163,7 +167,7 @@ type SimpleRouteConnection = {
163
167
  nominalTraceWidth?: number;
164
168
  /** @deprecated Use `nominalTraceWidth` instead. */
165
169
  width?: number;
166
- pointsToConnect: SimpleRoutePoint[];
170
+ pointsToConnect: SingleLayerConnectionPoint[];
167
171
  /** @deprecated DO NOT USE **/
168
172
  externallyConnectedPointIds?: string[][];
169
173
  };
@@ -1589,8 +1593,12 @@ interface RoutingPhaseDrcTolerances {
1589
1593
  minViaHoleDiameter?: number;
1590
1594
  minViaPadDiameter?: number;
1591
1595
  }
1596
+ interface PrecomputedRoutingResult {
1597
+ traces: SimplifiedPcbTrace[];
1598
+ outputSimpleRouteJson?: SimpleRouteJson;
1599
+ }
1592
1600
  interface RoutingPhasePlan {
1593
- getPrecomputedTraces?: (input: SimpleRouteJson) => SimplifiedPcbTrace[];
1601
+ getPrecomputedRoutingResult?: (input: SimpleRouteJson) => PrecomputedRoutingResult;
1594
1602
  routingPhaseIndex: number | null;
1595
1603
  phaseName?: AutoroutingPhaseProps["name"];
1596
1604
  routingPcbGroupId?: PcbGroupId;
@@ -193703,4 +193711,4 @@ declare module "react/jsx-runtime" {
193703
193711
  }
193704
193712
  }
193705
193713
 
193706
- export { Ammeter, AnalogAcSweepSimulation, AnalogAnalysisSimulation, AnalogDcOperatingPointSimulation, AnalogDcSweepSimulation, AnalogSimulation, AnalogSweepParameter, AnalogTransientSimulation, Antenna, AssemblyDevice, type AssemblyDeviceJsxProps, type AsyncEffect, type AutorouterCompleteEvent, type AutorouterErrorEvent, type AutorouterEvent, type AutorouterProgressEvent, type AutoroutingCacheDisabledReason, type AutoroutingCacheStatus, type AutoroutingEndEvent, type AutoroutingErrorEvent, type AutoroutingExecutionMetadata, AutoroutingPhase, type AutoroutingProgressEvent, type AutoroutingStartEvent, Battery, Board, Breakout, BreakoutPoint, Bus, CadAssembly, CadModel, Capacitor, Chip, Circuit, type CircuitJsonMetadata, type ComponentWithPins, Connector, Constraint, CopperPour, CopperText, CourtyardCircle, CourtyardOutline, CourtyardRect, Crystal, CurrentSource, Cutout, type DebugLogOutputEvent, DifferentialPair, Diode, DrcCheck, EnclosureCutoutAperture, EnclosureFdmBox, FabricationNoteDimension, FabricationNotePath, FabricationNoteRect, FabricationNoteText, Breakout as Fanout, BreakoutPoint as FanoutPoint, Fiducial, Footprint, Fuse, type GenericConnectionsAndSelectorsSel, type GenericLocalAutorouter, Group, Hole, type IIsolatedCircuit, type IRenderable, type IRootCircuit, Inductor, Interconnect, IsolatedCircuit, Jumper, Keepout, Led, type LocalCacheEngine, Mosfet, MountedBoard, Net, NetLabel, NormalComponent, type Obstacle, OpAmp, type PackingEndEvent, type PackingErrorEvent, type PackingStartEvent, Panel, type PcbGroupId, PcbNoteDimension, PcbNoteLine, PcbNotePath, PcbNoteRect, PcbNoteText, PcbTrace, PcbVia, PinHeader, type PinLabelSpec, Pinout, PlatedHole, Port, Potentiometer, PowerSource, PrimitiveComponent, Project, PushButton, type RenderPhase, type RenderPhaseFn, type RenderPhaseFunctions, type RenderPhaseStates, Renderable, Resistor, Resonator, RootCircuit, type RootCircuitEventName, SOLVERS, SchematicArc, SchematicBox, SchematicCell, SchematicCircle, SchematicGraphic, SchematicLine, SchematicPath, SchematicRect, SchematicRow, SchematicSection, SchematicSheet, SchematicSymbol, SchematicTable, SchematicText, type Sel, SilkscreenCircle, SilkscreenGraphic, SilkscreenLine, SilkscreenPath, SilkscreenRect, SilkscreenText, type SimpleRouteBounds, type SimpleRouteBus, type SimpleRouteBusTermination, type SimpleRouteConnection, type SimpleRouteDifferentialPair, type SimpleRouteJson, type SimpleRoutePoint, type SimplifiedPcbTrace, SmtPad, SolderJumper, type SolverEndedEvent, type SolverName, type SolverStartedEvent, SpiceModel, type SrjConnectionName, Subcircuit, Subpanel, Switch, SymbolComponent as Symbol, TestPoint, Trace, TraceHint, Transistor, Via, VoltageProbe, VoltageSource, analog, applyEditEvents, applyEditEventsToManualEditsFile, applyPcbEditEventsToManualEditsFile, applySchematicEditEventsToManualEditsFile, assembly, createUseComponent, enclosure, getPhaseTimingsFromRenderEvents, getSimpleRouteJsonFromCircuitJson, normalizePinLabels, orderedRenderPhases, renderPhaseIndexMap, resolveStaticFileImport, sel, unrouteCircuitJson, useCapacitor, useChip, useDiode, useLed, useRenderedCircuit, useResistor };
193714
+ export { Ammeter, AnalogAcSweepSimulation, AnalogAnalysisSimulation, AnalogDcOperatingPointSimulation, AnalogDcSweepSimulation, AnalogSimulation, AnalogSweepParameter, AnalogTransientSimulation, Antenna, AssemblyDevice, type AssemblyDeviceJsxProps, type AsyncEffect, type AutorouterCompleteEvent, type AutorouterErrorEvent, type AutorouterEvent, type AutorouterProgressEvent, type AutoroutingCacheDisabledReason, type AutoroutingCacheStatus, type AutoroutingEndEvent, type AutoroutingErrorEvent, type AutoroutingExecutionMetadata, AutoroutingPhase, type AutoroutingProgressEvent, type AutoroutingStartEvent, Battery, Board, Breakout, BreakoutPoint, Bus, CadAssembly, CadModel, Capacitor, Chip, Circuit, type CircuitJsonMetadata, type ComponentWithPins, Connector, Constraint, CopperPour, CopperText, CourtyardCircle, CourtyardOutline, CourtyardRect, Crystal, CurrentSource, Cutout, type DebugLogOutputEvent, DifferentialPair, Diode, DrcCheck, EnclosureCutoutAperture, EnclosureFdmBox, FabricationNoteDimension, FabricationNotePath, FabricationNoteRect, FabricationNoteText, Breakout as Fanout, BreakoutPoint as FanoutPoint, Fiducial, Footprint, Fuse, type GenericConnectionsAndSelectorsSel, type GenericLocalAutorouter, Group, Hole, type IIsolatedCircuit, type IRenderable, type IRootCircuit, Inductor, Interconnect, IsolatedCircuit, Jumper, Keepout, Led, type LocalCacheEngine, Mosfet, MountedBoard, Net, NetLabel, NormalComponent, type Obstacle, OpAmp, type PackingEndEvent, type PackingErrorEvent, type PackingStartEvent, Panel, type PcbGroupId, PcbNoteDimension, PcbNoteLine, PcbNotePath, PcbNoteRect, PcbNoteText, PcbTrace, PcbVia, PinHeader, type PinLabelSpec, Pinout, PlatedHole, Port, Potentiometer, PowerSource, PrimitiveComponent, Project, PushButton, type RenderPhase, type RenderPhaseFn, type RenderPhaseFunctions, type RenderPhaseStates, Renderable, Resistor, Resonator, RootCircuit, type RootCircuitEventName, SOLVERS, SchematicArc, SchematicBox, SchematicCell, SchematicCircle, SchematicGraphic, SchematicLine, SchematicPath, SchematicRect, SchematicRow, SchematicSection, SchematicSheet, SchematicSymbol, SchematicTable, SchematicText, type Sel, SilkscreenCircle, SilkscreenGraphic, SilkscreenLine, SilkscreenPath, SilkscreenRect, SilkscreenText, type SimpleRouteBounds, type SimpleRouteBus, type SimpleRouteBusTermination, type SimpleRouteConnection, type SimpleRouteDifferentialPair, type SimpleRouteJson, type SimpleRoutePoint, type SimplifiedPcbTrace, type SingleLayerConnectionPoint, SmtPad, SolderJumper, type SolverEndedEvent, type SolverName, type SolverStartedEvent, SpiceModel, type SrjConnectionName, Subcircuit, Subpanel, Switch, SymbolComponent as Symbol, TestPoint, Trace, TraceHint, Transistor, Via, VoltageProbe, VoltageSource, analog, applyEditEvents, applyEditEventsToManualEditsFile, applyPcbEditEventsToManualEditsFile, applySchematicEditEventsToManualEditsFile, assembly, createUseComponent, enclosure, getPhaseTimingsFromRenderEvents, getSimpleRouteJsonFromCircuitJson, normalizePinLabels, orderedRenderPhases, renderPhaseIndexMap, resolveStaticFileImport, sel, unrouteCircuitJson, useCapacitor, useChip, useDiode, useLed, useRenderedCircuit, useResistor };
package/dist/index.js CHANGED
@@ -16617,7 +16617,7 @@ import {
16617
16617
  } from "@tscircuit/checks";
16618
16618
  import { getBoundsFromPoints as getBoundsFromPoints10 } from "@tscircuit/math-utils";
16619
16619
  import { boardProps } from "@tscircuit/props";
16620
- import { compose as compose15, translate as translate15 } from "transformation-matrix";
16620
+ import { compose as compose16, translate as translate16 } from "transformation-matrix";
16621
16621
 
16622
16622
  // lib/utils/autorouting/getAncestorSubcircuitIds.ts
16623
16623
  var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
@@ -61216,8 +61216,190 @@ var Group_getFanoutPourNetMap = (group, routingPhasePlans) => {
61216
61216
  // lib/components/primitive-components/Group/Group_getRoutingPhasePlans.ts
61217
61217
  import { getBoundsFromPoints as getBoundsFromPoints8 } from "@tscircuit/math-utils";
61218
61218
 
61219
- // lib/components/primitive-components/Breakout/get-saved-fanout-traces.ts
61219
+ // lib/components/primitive-components/Group/get-saved-autorouting-phase-traces.ts
61220
61220
  import { applyToPoint as applyToPoint30, compose as compose12, translate as translate12 } from "transformation-matrix";
61221
+ var touchesEndpoint = (point6, endpoint) => Math.hypot(point6.x - endpoint.x, point6.y - endpoint.y) < 1e-4 && point6.layer === endpoint.layer;
61222
+ function getSavedAutoroutingPhaseTraces(phase, input, isFanout) {
61223
+ const group = phase.getGroup();
61224
+ const transformBeforeLayout = group._computePcbGlobalTransformBeforeLayout();
61225
+ const boardLayers = getViaBoardLayers(input.layerCount);
61226
+ const remainingPointsByConnection = new Map(
61227
+ input.connections.map((connection) => [
61228
+ connection,
61229
+ [...connection.pointsToConnect]
61230
+ ])
61231
+ );
61232
+ const coveredConnections = /* @__PURE__ */ new Set();
61233
+ const savedPorts = /* @__PURE__ */ new Set();
61234
+ const traces = [];
61235
+ for (const [pathIndex, path] of (phase._parsedProps.pcbTracePaths ?? []).entries()) {
61236
+ const port = phase.getSubcircuit().selectOne(path.connection, { type: "port" });
61237
+ if (!port)
61238
+ throw new Error(
61239
+ `Saved phase path "${path.connection}" must select a PCB port`
61240
+ );
61241
+ if (savedPorts.has(port))
61242
+ throw new Error(`Duplicate saved phase path for "${path.connection}"`);
61243
+ savedPorts.add(port);
61244
+ const connections = input.connections.filter(
61245
+ (connection2) => connection2.pointsToConnect.some(
61246
+ (point6) => point6.pcb_port_id === port.pcb_port_id
61247
+ )
61248
+ );
61249
+ if (connections.length !== 1) {
61250
+ throw new Error(
61251
+ `Saved phase path "${path.connection}" must select exactly one connection in this phase`
61252
+ );
61253
+ }
61254
+ const connection = connections[0];
61255
+ const remainingPoints = remainingPointsByConnection.get(connection);
61256
+ const startIndex = remainingPoints.findIndex(
61257
+ (point6) => point6.pcb_port_id === port.pcb_port_id
61258
+ );
61259
+ if (startIndex < 0)
61260
+ throw new Error(
61261
+ `Saved phase path "${path.connection}" starts at an endpoint already joined by another path`
61262
+ );
61263
+ const portBeforeLayout = port._getGlobalPcbPositionBeforeLayout();
61264
+ const portAfterLayout = port._getGlobalPcbPositionAfterLayout();
61265
+ const transform = compose12(
61266
+ translate12(
61267
+ portAfterLayout.x - portBeforeLayout.x,
61268
+ portAfterLayout.y - portBeforeLayout.y
61269
+ ),
61270
+ transformBeforeLayout
61271
+ );
61272
+ const route = path.route.map((point6) => ({
61273
+ ...point6,
61274
+ ...applyToPoint30(transform, point6)
61275
+ }));
61276
+ for (const point6 of route) {
61277
+ const layers = point6.route_type === "wire" ? [point6.layer] : [point6.from_layer, point6.to_layer];
61278
+ if (layers.some((layer) => !boardLayers.includes(layer))) {
61279
+ throw new Error(
61280
+ `Saved phase path "${path.connection}" uses a layer unavailable on this board`
61281
+ );
61282
+ }
61283
+ }
61284
+ const first = route[0];
61285
+ const last = route.at(-1);
61286
+ const firstLayer = first.route_type === "wire" ? first.layer : first.from_layer;
61287
+ const lastLayer = last.route_type === "wire" ? last.layer : last.to_layer;
61288
+ if (!touchesEndpoint(remainingPoints[startIndex], {
61289
+ ...first,
61290
+ layer: firstLayer
61291
+ })) {
61292
+ throw new Error(
61293
+ `Saved phase path "${path.connection}" must start at its PCB port on an available layer`
61294
+ );
61295
+ }
61296
+ const endIndex = remainingPoints.findIndex(
61297
+ (point6, index) => index !== startIndex && touchesEndpoint(point6, { ...last, layer: lastLayer })
61298
+ );
61299
+ if (!input.allowViaInPad && (first.route_type === "via" || last.route_type === "via" && endIndex >= 0)) {
61300
+ throw new Error(
61301
+ `Saved phase path "${path.connection}" has a via at a pad; enable allowViaInPad`
61302
+ );
61303
+ }
61304
+ const pcbTraceId = `saved_phase_${group.pcb_group_id}_${phase._parsedProps.phaseIndex ?? "default"}_${pathIndex}`;
61305
+ if (endIndex < 0 && !isFanout) {
61306
+ throw new Error(
61307
+ `Saved phase path "${path.connection}" must end at another connection endpoint; use autorouter="fanout" for saved escapes`
61308
+ );
61309
+ }
61310
+ if (endIndex >= 0) {
61311
+ remainingPoints.splice(startIndex, 1);
61312
+ } else {
61313
+ remainingPoints[startIndex] = {
61314
+ x: last.x,
61315
+ y: last.y,
61316
+ layer: lastLayer,
61317
+ pointId: `${pcbTraceId}_exit`
61318
+ };
61319
+ }
61320
+ const width = route.find((point6) => point6.route_type === "wire")?.width ?? input.minTraceWidth;
61321
+ const routeWithViaContacts = route.flatMap(
61322
+ (point6) => point6.route_type === "via" ? [
61323
+ {
61324
+ route_type: "wire",
61325
+ x: point6.x,
61326
+ y: point6.y,
61327
+ layer: point6.from_layer,
61328
+ width
61329
+ },
61330
+ point6,
61331
+ {
61332
+ route_type: "wire",
61333
+ x: point6.x,
61334
+ y: point6.y,
61335
+ layer: point6.to_layer,
61336
+ width
61337
+ }
61338
+ ] : [point6]
61339
+ );
61340
+ if (last.route_type === "via") {
61341
+ routeWithViaContacts.push({
61342
+ route_type: "wire",
61343
+ x: last.x,
61344
+ y: last.y,
61345
+ layer: last.to_layer,
61346
+ width
61347
+ });
61348
+ }
61349
+ coveredConnections.add(connection);
61350
+ traces.push({
61351
+ type: "pcb_trace",
61352
+ pcb_trace_id: pcbTraceId,
61353
+ connection_name: connection.name,
61354
+ connectsTo: [
61355
+ connection.source_trace_id,
61356
+ ...connection.pointsToConnect.map((point6) => point6.pointId)
61357
+ ].filter((id) => Boolean(id)),
61358
+ route: routeWithViaContacts
61359
+ });
61360
+ }
61361
+ for (const connection of input.connections) {
61362
+ if (!coveredConnections.has(connection)) {
61363
+ throw new Error(
61364
+ `pcbTracePaths must cover every connection in the phase; missing: ${connection.name}`
61365
+ );
61366
+ }
61367
+ if (!isFanout && remainingPointsByConnection.get(connection).length > 1) {
61368
+ throw new Error(
61369
+ `Saved phase paths for "${connection.name}" must connect every endpoint; use autorouter="fanout" for saved escapes`
61370
+ );
61371
+ }
61372
+ }
61373
+ const remainingConnections = input.connections.flatMap((connection) => {
61374
+ const pointsToConnect = remainingPointsByConnection.get(connection);
61375
+ return pointsToConnect.length > 1 ? [{ ...connection, pointsToConnect }] : [];
61376
+ });
61377
+ const remainingConnectionNames = new Set(
61378
+ remainingConnections.map((connection) => connection.name)
61379
+ );
61380
+ return {
61381
+ traces,
61382
+ outputSimpleRouteJson: isFanout ? {
61383
+ ...input,
61384
+ connections: remainingConnections,
61385
+ buses: input.buses?.map((bus) => ({
61386
+ ...bus,
61387
+ connectionNames: bus.connectionNames.filter(
61388
+ (name) => remainingConnectionNames.has(name)
61389
+ )
61390
+ })).filter((bus) => bus.connectionNames.length > 0),
61391
+ differentialPairs: input.differentialPairs?.filter(
61392
+ (pair) => pair.connectionNames.every(
61393
+ (name) => remainingConnectionNames.has(name)
61394
+ )
61395
+ ),
61396
+ traces: [...input.traces ?? [], ...traces]
61397
+ } : void 0
61398
+ };
61399
+ }
61400
+
61401
+ // lib/components/primitive-components/Breakout/get-saved-fanout-traces.ts
61402
+ import { applyToPoint as applyToPoint31, compose as compose13, translate as translate13 } from "transformation-matrix";
61221
61403
 
61222
61404
  // lib/components/primitive-components/BreakoutPoint.ts
61223
61405
  import { breakoutPointProps } from "@tscircuit/props";
@@ -61381,13 +61563,13 @@ function getSavedFanoutTraces(breakout, input) {
61381
61563
  );
61382
61564
  const pcbExit = db.pcb_breakout_point.get(exit.pcb_breakout_point_id);
61383
61565
  const localExit = path.route.at(-1);
61384
- const transform = compose12(
61566
+ const transform = compose13(
61385
61567
  exit._computePcbGlobalTransformBeforeLayout(),
61386
- translate12(-localExit.x, -localExit.y)
61568
+ translate13(-localExit.x, -localExit.y)
61387
61569
  );
61388
- const originalExit = applyToPoint30(transform, localExit);
61570
+ const originalExit = applyToPoint31(transform, localExit);
61389
61571
  const route = path.route.map((point6) => {
61390
- const position = applyToPoint30(transform, point6);
61572
+ const position = applyToPoint31(transform, point6);
61391
61573
  return {
61392
61574
  ...point6,
61393
61575
  x: position.x + pcbExit.x - originalExit.x,
@@ -61415,7 +61597,7 @@ function getSavedFanoutTraces(breakout, input) {
61415
61597
  ];
61416
61598
  if (connection.pointsToConnect.some(
61417
61599
  (point6) => !endpoints.some(
61418
- (endpoint) => Math.hypot(point6.x - endpoint.x, point6.y - endpoint.y) < 1e-4 && (point6.layers ?? [point6.layer]).includes(endpoint.layer)
61600
+ (endpoint) => Math.hypot(point6.x - endpoint.x, point6.y - endpoint.y) < 1e-4 && point6.layer === endpoint.layer
61419
61601
  )
61420
61602
  ))
61421
61603
  throw new Error(
@@ -61546,15 +61728,21 @@ function convertPortSelectorToEndpointKey(selector) {
61546
61728
  return selector.trim().replace(/\s*>\s*/g, ".").replace(/\s+/g, ".").replace(/^\./, "").replace(/\.\./g, ".");
61547
61729
  }
61548
61730
  function getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps) {
61731
+ if (phaseProps.connection === void 0 && phaseProps.connections === void 0) {
61732
+ return phaseProps.pcbTracePaths?.map((path) => path.connection) ?? [];
61733
+ }
61549
61734
  return [
61550
61735
  ...phaseProps.connection ? [phaseProps.connection] : [],
61551
61736
  ...phaseProps.connections ?? []
61552
61737
  ];
61553
61738
  }
61554
61739
  function traceHasEndpointMatchingConnectionSelector(trace, connectionSelectorEndpointKey) {
61555
- return trace.getTracePortPathSelectors().some(
61740
+ if (trace.getTracePortPathSelectors().some(
61556
61741
  (selector) => convertPortSelectorToEndpointKey(selector) === connectionSelectorEndpointKey
61557
- );
61742
+ ))
61743
+ return true;
61744
+ const port = trace.getSubcircuit().selectOne(connectionSelectorEndpointKey, { type: "port" });
61745
+ return port !== null && (trace._findConnectedPorts().ports?.includes(port) ?? false);
61558
61746
  }
61559
61747
  function getAutoroutersByPhaseIndex(group) {
61560
61748
  const autoroutingPhases = group.selectAll(
@@ -61698,7 +61886,7 @@ function Group_getRoutingPhasePlans(group) {
61698
61886
  }
61699
61887
  }
61700
61888
  }
61701
- if (phaseProps.reroute) {
61889
+ if (phaseProps.reroute || phaseProps.pcbTracePaths !== void 0) {
61702
61890
  getOrCreateRoutingPhasePlan(plansByPhaseIndex, phaseIndex);
61703
61891
  }
61704
61892
  }
@@ -61721,6 +61909,18 @@ function Group_getRoutingPhasePlans(group) {
61721
61909
  plan.fanoutPourNetMap = phaseProps?.fanoutPourNetMap ?? groupFanoutProps.fanoutPourNetMap;
61722
61910
  plan.drcTolerances = phaseProps ? getDrcTolerancesFromAutoroutingPhaseProps(phaseProps) : void 0;
61723
61911
  }
61912
+ for (const phase of group.selectAll(
61913
+ "autoroutingphase"
61914
+ )) {
61915
+ if (phase._parsedProps.pcbTracePaths === void 0) continue;
61916
+ const plan = plansByPhaseIndex.get(phase._parsedProps.phaseIndex ?? null);
61917
+ if (!plan) continue;
61918
+ const config = plan.autorouter !== void 0 ? getPresetAutoroutingConfig(plan.autorouter, group.root?.platform) : group._getAutorouterConfig();
61919
+ const isFanout = ["fanout", "single_layer_fanout"].includes(
61920
+ config.preset ?? ""
61921
+ );
61922
+ plan.getPrecomputedRoutingResult = (input) => getSavedAutoroutingPhaseTraces(phase, input, isFanout);
61923
+ }
61724
61924
  const breakoutPlans = [];
61725
61925
  for (const breakout of breakouts) {
61726
61926
  const breakoutProps2 = breakout._parsedProps;
@@ -61771,7 +61971,9 @@ function Group_getRoutingPhasePlans(group) {
61771
61971
  groupMode: "subcircuit",
61772
61972
  allowViaInPad: (typeof breakoutProps2.autorouter === "object" ? breakoutProps2.autorouter.allowViaInPad : void 0) ?? group._getAutorouterConfig().allowViaInPad
61773
61973
  },
61774
- getPrecomputedTraces: (input) => getSavedFanoutTraces(breakout, input)
61974
+ getPrecomputedRoutingResult: (input) => ({
61975
+ traces: getSavedFanoutTraces(breakout, input)
61976
+ })
61775
61977
  });
61776
61978
  continue;
61777
61979
  }
@@ -61833,7 +62035,7 @@ function Group_getRoutingPhasePlans(group) {
61833
62035
  var package_default = {
61834
62036
  name: "@tscircuit/core",
61835
62037
  type: "module",
61836
- version: "0.0.1900",
62038
+ version: "0.0.1902",
61837
62039
  types: "dist/index.d.ts",
61838
62040
  main: "dist/index.js",
61839
62041
  module: "dist/index.js",
@@ -62311,7 +62513,6 @@ function Group_syncFanoutExitsWithGlobalConnections({
62311
62513
  previousPoint
62312
62514
  } of globalPointMatches) {
62313
62515
  const {
62314
- layers: _previousLayers,
62315
62516
  terminalVia: _previousTerminalVia,
62316
62517
  ...previousPointWithoutLayerOverrides
62317
62518
  } = previousPoint;
@@ -62320,7 +62521,6 @@ function Group_syncFanoutExitsWithGlobalConnections({
62320
62521
  x: fanoutExitPoint.x,
62321
62522
  y: fanoutExitPoint.y,
62322
62523
  layer: fanoutExitPoint.layer,
62323
- ...fanoutExitPoint.layers ? { layers: [...fanoutExitPoint.layers] } : {},
62324
62524
  ...fanoutExitPoint.terminalVia ? { terminalVia: { ...fanoutExitPoint.terminalVia } } : {}
62325
62525
  };
62326
62526
  globalConnection.pointsToConnect[pointIndex] = synchronizedGlobalPoint;
@@ -63691,10 +63891,14 @@ var Group5 = class extends NormalComponent3 {
63691
63891
  });
63692
63892
  };
63693
63893
  const routingStages = routingPhasePlans.flatMap((routingPhasePlan) => {
63694
- const phaseAutorouterConfig = routingPhasePlan.autorouter ? getPresetAutoroutingConfig(
63894
+ const resolvedPhaseAutorouterConfig = routingPhasePlan.autorouter ? getPresetAutoroutingConfig(
63695
63895
  routingPhasePlan.autorouter,
63696
63896
  this.root?.platform
63697
63897
  ) : autorouterConfig;
63898
+ const phaseAutorouterConfig = routingPhasePlan.getPrecomputedRoutingResult ? {
63899
+ ...resolvedPhaseAutorouterConfig,
63900
+ allowViaInPad: (typeof routingPhasePlan.autorouter === "object" ? routingPhasePlan.autorouter.allowViaInPad : void 0) ?? autorouterConfig.allowViaInPad
63901
+ } : resolvedPhaseAutorouterConfig;
63698
63902
  const stages = getLocalAutoroutingStages(
63699
63903
  phaseAutorouterConfig,
63700
63904
  this.root?.platform
@@ -63964,10 +64168,11 @@ var Group5 = class extends NormalComponent3 {
63964
64168
  routingPhasePlan.drcTolerances
63965
64169
  );
63966
64170
  simpleRouteJson.allowViaInPad = phaseAutorouterConfig.allowViaInPad;
64171
+ const getPrecomputedRoutingResult = usesPreviousStageOutput ? void 0 : routingPhasePlan.getPrecomputedRoutingResult;
63967
64172
  const simplificationHasNoTraceInput = Boolean(
63968
64173
  isTraceSimplificationPhase && simpleRouteJson.traces?.length === 0
63969
64174
  );
63970
- if ((hasPhasedAutorouting || isReroutePhase) && (simpleRouteJson.connections.length === 0 && !isTraceSimplificationPhase || simplificationHasNoTraceInput)) {
64175
+ if ((hasPhasedAutorouting || isReroutePhase || usesPreviousStageOutput) && (simpleRouteJson.connections.length === 0 && !isTraceSimplificationPhase && !getPrecomputedRoutingResult || simplificationHasNoTraceInput)) {
63971
64176
  if (phaseStageIndex === 0) {
63972
64177
  emitRoutingPhaseDebugObject(routingPhasePlan, simpleRouteJson.bounds);
63973
64178
  }
@@ -63983,7 +64188,7 @@ var Group5 = class extends NormalComponent3 {
63983
64188
  }
63984
64189
  }
63985
64190
  const fanoutMode = phaseAutorouterConfig.preset;
63986
- if ((fanoutMode === "fanout" || fanoutMode === "single_layer_fanout") && !routingPhasePlan.fanoutRegionPcbGroupId) {
64191
+ if ((fanoutMode === "fanout" || fanoutMode === "single_layer_fanout") && !routingPhasePlan.fanoutRegionPcbGroupId && !getPrecomputedRoutingResult) {
63987
64192
  routingPhasePlan.fanoutBounds = FanoutAutorouter.resolveFanoutBounds(
63988
64193
  simpleRouteJson,
63989
64194
  {
@@ -64029,8 +64234,8 @@ var Group5 = class extends NormalComponent3 {
64029
64234
  autorouterVersion: autorouterVersion2,
64030
64235
  effort
64031
64236
  };
64032
- const autorouterName = routingPhasePlan.getPrecomputedTraces ? "precomputed" : phaseAutorouterConfig.algorithmFn ? "custom" : localAutorouterStrategy.name;
64033
- const solverName = routingPhasePlan.getPrecomputedTraces || phaseAutorouterConfig.algorithmFn ? void 0 : localAutorouterStrategy.getSolverName(commonAutorouterOptions);
64237
+ const autorouterName = getPrecomputedRoutingResult ? "precomputed" : phaseAutorouterConfig.algorithmFn ? "custom" : localAutorouterStrategy.name;
64238
+ const solverName = getPrecomputedRoutingResult || phaseAutorouterConfig.algorithmFn ? void 0 : localAutorouterStrategy.getSolverName(commonAutorouterOptions);
64034
64239
  const localAutoroutingCacheSolverOptions = {
64035
64240
  autorouterName,
64036
64241
  solverName,
@@ -64043,13 +64248,13 @@ var Group5 = class extends NormalComponent3 {
64043
64248
  autorouterVersion: commonAutorouterOptions.autorouterVersion,
64044
64249
  effort: commonAutorouterOptions.effort
64045
64250
  };
64046
- const cacheEngine = routingPhasePlan.getPrecomputedTraces || phaseAutorouterConfig.algorithmFn || !localAutorouterStrategy.cacheable ? void 0 : this.root?.platform?.localCacheEngine;
64251
+ const cacheEngine = getPrecomputedRoutingResult || phaseAutorouterConfig.algorithmFn || !localAutorouterStrategy.cacheable ? void 0 : this.root?.platform?.localCacheEngine;
64047
64252
  const cacheKey = cacheEngine ? getLocalAutoroutingCacheKey(
64048
64253
  simpleRouteJson,
64049
64254
  localAutoroutingCacheSolverOptions
64050
64255
  ) : void 0;
64051
64256
  const cachedResult = cacheKey ? await getCachedLocalAutoroutingPhaseResult({ cacheEngine, cacheKey }) : null;
64052
- const cacheDisabledReason = routingPhasePlan.getPrecomputedTraces ? "precomputed" : phaseAutorouterConfig.algorithmFn ? "custom_algorithm" : !localAutorouterStrategy.cacheable ? "strategy_not_cacheable" : !cacheEngine ? "no_cache_engine" : void 0;
64257
+ const cacheDisabledReason = getPrecomputedRoutingResult ? "precomputed" : phaseAutorouterConfig.algorithmFn ? "custom_algorithm" : !localAutorouterStrategy.cacheable ? "strategy_not_cacheable" : !cacheEngine ? "no_cache_engine" : void 0;
64053
64258
  const autoroutingMetadata = {
64054
64259
  routingPhaseIndex: routingStageIndex,
64055
64260
  phaseOrdinal: routingStageIndex + 1,
@@ -64081,8 +64286,11 @@ var Group5 = class extends NormalComponent3 {
64081
64286
  let autorouter;
64082
64287
  try {
64083
64288
  let traces;
64084
- if (routingPhasePlan.getPrecomputedTraces) {
64085
- traces = routingPhasePlan.getPrecomputedTraces(simpleRouteJson);
64289
+ let precomputedOutputSimpleRouteJson;
64290
+ if (getPrecomputedRoutingResult) {
64291
+ const result = getPrecomputedRoutingResult(simpleRouteJson);
64292
+ traces = result.traces;
64293
+ precomputedOutputSimpleRouteJson = result.outputSimpleRouteJson;
64086
64294
  for (const trace of traces)
64087
64295
  fixedFanoutTraceIds.add(trace.pcb_trace_id);
64088
64296
  } else if (cachedResult) {
@@ -64148,7 +64356,7 @@ var Group5 = class extends NormalComponent3 {
64148
64356
  activeAutorouter.start();
64149
64357
  traces = await routingPromise;
64150
64358
  }
64151
- let transformedSimpleRouteJson = autorouter?.getOutputSimpleRouteJson?.();
64359
+ let transformedSimpleRouteJson = precomputedOutputSimpleRouteJson ?? autorouter?.getOutputSimpleRouteJson?.();
64152
64360
  if (transformedSimpleRouteJson && !usesPreviousStageOutput && ["fanout", "single_layer_fanout"].includes(
64153
64361
  phaseAutorouterConfig.preset ?? ""
64154
64362
  ) && routingPhasePlan.routingPcbGroupId) {
@@ -65088,7 +65296,7 @@ function inflateSourceInductor(sourceElm, inflatorContext) {
65088
65296
  import { ledProps } from "@tscircuit/props";
65089
65297
 
65090
65298
  // lib/components/normal-components/Led_addPolarityFabricationSymbol.ts
65091
- import { applyToPoint as applyToPoint31, compose as compose13, rotate as rotate6, translate as translate13 } from "transformation-matrix";
65299
+ import { applyToPoint as applyToPoint32, compose as compose14, rotate as rotate6, translate as translate14 } from "transformation-matrix";
65092
65300
  var generatedNotes = /* @__PURE__ */ new WeakMap();
65093
65301
  var getPolarity2 = (port) => {
65094
65302
  const hints = [port.name, ...port.port_hints ?? []].map(
@@ -65129,11 +65337,11 @@ var Led_addPolarityFabricationSymbol = (led) => {
65129
65337
  const distance22 = Math.hypot(k.x - a.x, k.y - a.y);
65130
65338
  if (distance22 < 1e-6) return;
65131
65339
  const angle = Math.atan2(k.y - a.y, k.x - a.x);
65132
- const frame = compose13(
65133
- translate13((a.x + k.x) / 2, (a.y + k.y) / 2),
65340
+ const frame = compose14(
65341
+ translate14((a.x + k.x) / 2, (a.y + k.y) / 2),
65134
65342
  rotate6(angle)
65135
65343
  );
65136
- const point6 = (x, y) => applyToPoint31(frame, { x, y });
65344
+ const point6 = (x, y) => applyToPoint32(frame, { x, y });
65137
65345
  const common = {
65138
65346
  pcb_component_id: pcb.pcb_component_id,
65139
65347
  subcircuit_id: led.getSubcircuit()?.subcircuit_id ?? void 0,
@@ -67248,10 +67456,10 @@ import {
67248
67456
  Polygon as Polygon2,
67249
67457
  Segment
67250
67458
  } from "@flatten-js/core";
67251
- import { compose as compose14, rotate as rotate7, translate as translate14 } from "transformation-matrix";
67459
+ import { compose as compose15, rotate as rotate7, translate as translate15 } from "transformation-matrix";
67252
67460
  var placePolygon = (polygon, center, degrees = 0) => {
67253
- const { a, b, c, d, e, f } = compose14(
67254
- translate14(center.x, center.y),
67461
+ const { a, b, c, d, e, f } = compose15(
67462
+ translate15(center.x, center.y),
67255
67463
  rotate7(degrees * Math.PI / 180)
67256
67464
  );
67257
67465
  return polygon.transform(new Matrix(a, b, c, d, e, f));
@@ -67940,9 +68148,9 @@ var Board = class extends Group5 {
67940
68148
  _computePcbGlobalTransformBeforeLayout() {
67941
68149
  if (this._panelPositionOffset) {
67942
68150
  const parentTransform = this.parent?._computePcbGlobalTransformBeforeLayout?.() ?? { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
67943
- return compose15(
68151
+ return compose16(
67944
68152
  parentTransform,
67945
- translate15(this._panelPositionOffset.x, this._panelPositionOffset.y)
68153
+ translate16(this._panelPositionOffset.x, this._panelPositionOffset.y)
67946
68154
  );
67947
68155
  }
67948
68156
  return super._computePcbGlobalTransformBeforeLayout();
@@ -68573,7 +68781,7 @@ import { distance as distance20 } from "circuit-json";
68573
68781
  // lib/components/normal-components/Subpanel.ts
68574
68782
  import { subpanelProps } from "@tscircuit/props";
68575
68783
  import { distance as distance19 } from "circuit-json";
68576
- import { compose as compose16, identity as identity8, translate as translate16 } from "transformation-matrix";
68784
+ import { compose as compose17, identity as identity8, translate as translate17 } from "transformation-matrix";
68577
68785
 
68578
68786
  // lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
68579
68787
  import * as Flatten from "@flatten-js/core";
@@ -69085,9 +69293,9 @@ var Subpanel = class _Subpanel extends Group5 {
69085
69293
  _computePcbGlobalTransformBeforeLayout() {
69086
69294
  if (this._panelPositionOffset) {
69087
69295
  const parentTransform = this.parent?._computePcbGlobalTransformBeforeLayout?.() ?? identity8();
69088
- return compose16(
69296
+ return compose17(
69089
69297
  parentTransform,
69090
- translate16(this._panelPositionOffset.x, this._panelPositionOffset.y)
69298
+ translate17(this._panelPositionOffset.x, this._panelPositionOffset.y)
69091
69299
  );
69092
69300
  }
69093
69301
  return super._computePcbGlobalTransformBeforeLayout();
@@ -70754,7 +70962,7 @@ var AutoroutingPhase = class extends PrimitiveComponent2 {
70754
70962
 
70755
70963
  // lib/components/primitive-components/FabricationNoteDimension.ts
70756
70964
  import { fabricationNoteDimensionProps } from "@tscircuit/props";
70757
- import { applyToPoint as applyToPoint32 } from "transformation-matrix";
70965
+ import { applyToPoint as applyToPoint33 } from "transformation-matrix";
70758
70966
  var FabricationNoteDimension = class extends PrimitiveComponent2 {
70759
70967
  fabrication_note_dimension_id = null;
70760
70968
  isPcbPrimitive = true;
@@ -70773,13 +70981,13 @@ var FabricationNoteDimension = class extends PrimitiveComponent2 {
70773
70981
  this.renderError(
70774
70982
  `FabricationNoteDimension could not find selector "${input}"`
70775
70983
  );
70776
- return applyToPoint32(transform, { x: 0, y: 0 });
70984
+ return applyToPoint33(transform, { x: 0, y: 0 });
70777
70985
  }
70778
70986
  return target._getGlobalPcbPositionBeforeLayout();
70779
70987
  }
70780
70988
  const numericX = typeof input.x === "string" ? parseFloat(input.x) : input.x;
70781
70989
  const numericY = typeof input.y === "string" ? parseFloat(input.y) : input.y;
70782
- return applyToPoint32(transform, { x: numericX, y: numericY });
70990
+ return applyToPoint33(transform, { x: numericX, y: numericY });
70783
70991
  }
70784
70992
  doInitialPcbPrimitiveRender() {
70785
70993
  if (this.root?.pcbDisabled) return;
@@ -70874,7 +71082,7 @@ var FabricationNoteDimension = class extends PrimitiveComponent2 {
70874
71082
 
70875
71083
  // lib/components/primitive-components/PcbNoteDimension.ts
70876
71084
  import { pcbNoteDimensionProps } from "@tscircuit/props";
70877
- import { applyToPoint as applyToPoint33 } from "transformation-matrix";
71085
+ import { applyToPoint as applyToPoint34 } from "transformation-matrix";
70878
71086
  var PcbNoteDimension = class extends PrimitiveComponent2 {
70879
71087
  pcb_note_dimension_id = null;
70880
71088
  isPcbPrimitive = true;
@@ -70891,7 +71099,7 @@ var PcbNoteDimension = class extends PrimitiveComponent2 {
70891
71099
  );
70892
71100
  if (!target) {
70893
71101
  this.renderError(`PcbNoteDimension could not find selector "${input}"`);
70894
- return applyToPoint33(transform, { x: 0, y: 0 });
71102
+ return applyToPoint34(transform, { x: 0, y: 0 });
70895
71103
  }
70896
71104
  const targetPcbComponentId = target.pcb_component_id;
70897
71105
  const root = this.root;
@@ -70908,7 +71116,7 @@ var PcbNoteDimension = class extends PrimitiveComponent2 {
70908
71116
  }
70909
71117
  const numericX = typeof input.x === "string" ? parseFloat(input.x) : input.x;
70910
71118
  const numericY = typeof input.y === "string" ? parseFloat(input.y) : input.y;
70911
- return applyToPoint33(transform, { x: numericX, y: numericY });
71119
+ return applyToPoint34(transform, { x: numericX, y: numericY });
70912
71120
  }
70913
71121
  doInitialPcbPrimitiveRender() {
70914
71122
  if (this.root?.pcbDisabled) return;
@@ -73659,7 +73867,7 @@ import {
73659
73867
  getTransformedSvgPathRoutes,
73660
73868
  loadImageSource
73661
73869
  } from "@tscircuit/image-utils";
73662
- import { applyToPoint as applyToPoint34 } from "transformation-matrix";
73870
+ import { applyToPoint as applyToPoint35 } from "transformation-matrix";
73663
73871
  var SilkscreenGraphic = class extends PrimitiveComponent2 {
73664
73872
  pcb_silkscreen_graphic_id = null;
73665
73873
  pcb_silkscreen_graphic_ids = [];
@@ -73761,7 +73969,7 @@ var SilkscreenGraphic = class extends PrimitiveComponent2 {
73761
73969
  { x: halfWidth, y: -halfHeight },
73762
73970
  { x: -halfWidth, y: -halfHeight }
73763
73971
  ]).map(
73764
- (point6) => applyToPoint34(transform, point6)
73972
+ (point6) => applyToPoint35(transform, point6)
73765
73973
  )
73766
73974
  },
73767
73975
  inner_rings: []
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1901",
4
+ "version": "0.0.1903",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",