@tscircuit/core 0.0.1999 → 0.0.2000

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 +488 -478
  2. package/dist/index.js +381 -244
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -222,7 +222,7 @@ function createPcbFold(records, thickness) {
222
222
  }
223
223
  return result;
224
224
  };
225
- const inverse2 = ({
225
+ const inverse3 = ({
226
226
  p,
227
227
  anchor,
228
228
  direction
@@ -243,8 +243,8 @@ function createPcbFold(records, thickness) {
243
243
  };
244
244
  return {
245
245
  bends,
246
- inversePoint: (p, anchor) => inverse2({ p, anchor, direction: false }),
247
- inverseDirection: (p, anchor) => inverse2({ p, anchor, direction: true }),
246
+ inversePoint: (p, anchor) => inverse3({ p, anchor, direction: false }),
247
+ inverseDirection: (p, anchor) => inverse3({ p, anchor, direction: true }),
248
248
  point: (p, anchor = p) => transform({ p, anchor, direction: false }),
249
249
  direction: (p, anchor) => transform({ p, anchor, direction: true }),
250
250
  assertRigid(points, label) {
@@ -18875,6 +18875,314 @@ function inflateSourceFiducial(sourceElm, inflatorContext) {
18875
18875
  }
18876
18876
  }
18877
18877
 
18878
+ // lib/components/primitive-components/Group/get-autorouting-phase-pcb-trace-paths.ts
18879
+ import { fanoutTracePath as fanoutTracePath2 } from "@tscircuit/props";
18880
+ import { applyToPoint as applyToPoint28, inverse as inverse2 } from "transformation-matrix";
18881
+
18882
+ // lib/components/primitive-components/Group/get-saved-pcb-trace-path-transform.ts
18883
+ import { compose as compose9, translate as translate7 } from "transformation-matrix";
18884
+ function getSavedPcbTracePathTransform(group, port) {
18885
+ const before = port._getGlobalPcbPositionBeforeLayout();
18886
+ const after = port._getGlobalPcbPositionAfterLayout();
18887
+ return compose9(
18888
+ translate7(after.x - before.x, after.y - before.y),
18889
+ group._computePcbGlobalTransformBeforeLayout()
18890
+ );
18891
+ }
18892
+
18893
+ // lib/components/primitive-components/Group/get-saved-autorouting-phase-traces.ts
18894
+ import { applyToPoint as applyToPoint27 } from "transformation-matrix";
18895
+ import "@tscircuit/props";
18896
+ var touchesEndpoint = (point6, endpoint) => Math.hypot(point6.x - endpoint.x, point6.y - endpoint.y) < 1e-4 && point6.layer === endpoint.layer;
18897
+ function getSavedAutoroutingPhaseTraces(phase, input, isFanout) {
18898
+ return getSavedAutoroutingPhaseTracesFromPaths({
18899
+ group: phase.getGroup(),
18900
+ subcircuit: phase.getSubcircuit(),
18901
+ paths: phase._parsedProps.pcbTracePaths ?? [],
18902
+ phaseIndex: phase._parsedProps.phaseIndex,
18903
+ input,
18904
+ isFanout
18905
+ });
18906
+ }
18907
+ function getSavedAutoroutingPhaseTracesFromPaths({
18908
+ group,
18909
+ subcircuit,
18910
+ paths,
18911
+ phaseIndex,
18912
+ input,
18913
+ isFanout
18914
+ }) {
18915
+ const boardLayers = getViaBoardLayers(input.layerCount);
18916
+ const remainingPointsByConnection = new Map(
18917
+ input.connections.map((connection) => [
18918
+ connection,
18919
+ [...connection.pointsToConnect]
18920
+ ])
18921
+ );
18922
+ const coveredConnections = /* @__PURE__ */ new Set();
18923
+ const savedPorts = /* @__PURE__ */ new Set();
18924
+ const traces = [];
18925
+ for (const [pathIndex, path] of paths.entries()) {
18926
+ const port = subcircuit.selectOne(path.connection, {
18927
+ type: "port"
18928
+ });
18929
+ if (!port)
18930
+ throw new Error(
18931
+ `Saved phase path "${path.connection}" must select a PCB port`
18932
+ );
18933
+ if (savedPorts.has(port))
18934
+ throw new Error(`Duplicate saved phase path for "${path.connection}"`);
18935
+ savedPorts.add(port);
18936
+ const connections = input.connections.filter(
18937
+ (connection2) => connection2.pointsToConnect.some(
18938
+ (point6) => point6.pcb_port_id === port.pcb_port_id
18939
+ )
18940
+ );
18941
+ if (connections.length !== 1) {
18942
+ throw new Error(
18943
+ `Saved phase path "${path.connection}" must select exactly one connection in this phase`
18944
+ );
18945
+ }
18946
+ const connection = connections[0];
18947
+ const remainingPoints = remainingPointsByConnection.get(connection);
18948
+ const startIndex = remainingPoints.findIndex(
18949
+ (point6) => point6.pcb_port_id === port.pcb_port_id
18950
+ );
18951
+ if (startIndex < 0)
18952
+ throw new Error(
18953
+ `Saved phase path "${path.connection}" starts at an endpoint already joined by another path`
18954
+ );
18955
+ const transform = getSavedPcbTracePathTransform(group, port);
18956
+ const route = path.route.map((point6) => ({
18957
+ ...point6,
18958
+ ...applyToPoint27(transform, point6)
18959
+ }));
18960
+ for (const point6 of route) {
18961
+ const layers = point6.route_type === "wire" ? [point6.layer] : [point6.from_layer, point6.to_layer];
18962
+ if (layers.some((layer) => !boardLayers.includes(layer))) {
18963
+ throw new Error(
18964
+ `Saved phase path "${path.connection}" uses a layer unavailable on this board`
18965
+ );
18966
+ }
18967
+ }
18968
+ const first = route[0];
18969
+ const last = route.at(-1);
18970
+ const firstLayer = first.route_type === "wire" ? first.layer : first.from_layer;
18971
+ const lastLayer = last.route_type === "wire" ? last.layer : last.to_layer;
18972
+ if (!touchesEndpoint(remainingPoints[startIndex], {
18973
+ ...first,
18974
+ layer: firstLayer
18975
+ })) {
18976
+ throw new Error(
18977
+ `Saved phase path "${path.connection}" must start at its PCB port on an available layer`
18978
+ );
18979
+ }
18980
+ const endIndex = remainingPoints.findIndex(
18981
+ (point6, index) => index !== startIndex && touchesEndpoint(point6, { ...last, layer: lastLayer })
18982
+ );
18983
+ if (!input.allowViaInPad && (first.route_type === "via" || last.route_type === "via" && endIndex >= 0)) {
18984
+ throw new Error(
18985
+ `Saved phase path "${path.connection}" has a via at a pad; enable allowViaInPad`
18986
+ );
18987
+ }
18988
+ const pcbTraceId = `saved_phase_${group.pcb_group_id}_${phaseIndex ?? "default"}_${pathIndex}`;
18989
+ if (endIndex < 0 && !isFanout) {
18990
+ throw new Error(
18991
+ `Saved phase path "${path.connection}" must end at another connection endpoint; use autorouter="fanout" for saved escapes`
18992
+ );
18993
+ }
18994
+ if (endIndex >= 0) {
18995
+ remainingPoints.splice(startIndex, 1);
18996
+ } else {
18997
+ remainingPoints[startIndex] = {
18998
+ x: last.x,
18999
+ y: last.y,
19000
+ layer: lastLayer,
19001
+ pointId: `${pcbTraceId}_exit`
19002
+ };
19003
+ }
19004
+ const width = route.find((point6) => point6.route_type === "wire")?.width ?? input.minTraceWidth;
19005
+ const routeWithViaContacts = route.flatMap(
19006
+ (point6) => point6.route_type === "via" ? [
19007
+ {
19008
+ route_type: "wire",
19009
+ x: point6.x,
19010
+ y: point6.y,
19011
+ layer: point6.from_layer,
19012
+ width
19013
+ },
19014
+ point6,
19015
+ {
19016
+ route_type: "wire",
19017
+ x: point6.x,
19018
+ y: point6.y,
19019
+ layer: point6.to_layer,
19020
+ width
19021
+ }
19022
+ ] : [point6]
19023
+ );
19024
+ if (last.route_type === "via") {
19025
+ routeWithViaContacts.push({
19026
+ route_type: "wire",
19027
+ x: last.x,
19028
+ y: last.y,
19029
+ layer: last.to_layer,
19030
+ width
19031
+ });
19032
+ }
19033
+ coveredConnections.add(connection);
19034
+ traces.push({
19035
+ type: "pcb_trace",
19036
+ pcb_trace_id: pcbTraceId,
19037
+ connection_name: connection.name,
19038
+ connectsTo: [
19039
+ connection.source_trace_id,
19040
+ ...connection.pointsToConnect.map((point6) => point6.pointId)
19041
+ ].filter((id) => Boolean(id)),
19042
+ route: routeWithViaContacts
19043
+ });
19044
+ }
19045
+ for (const connection of input.connections) {
19046
+ if (!coveredConnections.has(connection)) {
19047
+ throw new Error(
19048
+ `pcbTracePaths must cover every connection in the phase; missing: ${connection.name}`
19049
+ );
19050
+ }
19051
+ if (!isFanout && remainingPointsByConnection.get(connection).length > 1) {
19052
+ throw new Error(
19053
+ `Saved phase paths for "${connection.name}" must connect every endpoint; use autorouter="fanout" for saved escapes`
19054
+ );
19055
+ }
19056
+ }
19057
+ const remainingConnections = input.connections.flatMap((connection) => {
19058
+ const pointsToConnect = remainingPointsByConnection.get(connection);
19059
+ return pointsToConnect.length > 1 ? [{ ...connection, pointsToConnect }] : [];
19060
+ });
19061
+ const remainingConnectionNames = new Set(
19062
+ remainingConnections.map((connection) => connection.name)
19063
+ );
19064
+ return {
19065
+ traces,
19066
+ outputSimpleRouteJson: isFanout ? {
19067
+ ...input,
19068
+ connections: remainingConnections,
19069
+ buses: input.buses?.map((bus) => ({
19070
+ ...bus,
19071
+ connectionNames: bus.connectionNames.filter(
19072
+ (name) => remainingConnectionNames.has(name)
19073
+ )
19074
+ })).filter((bus) => bus.connectionNames.length > 0),
19075
+ differentialPairs: input.differentialPairs?.filter(
19076
+ (pair) => pair.connectionNames.every(
19077
+ (name) => remainingConnectionNames.has(name)
19078
+ )
19079
+ ),
19080
+ traces: [...input.traces ?? [], ...traces]
19081
+ } : void 0
19082
+ };
19083
+ }
19084
+
19085
+ // lib/components/primitive-components/Group/get-autorouting-phase-pcb-trace-paths.ts
19086
+ var touches = (point6, terminal, end = false) => Math.hypot(point6.x - terminal.x, point6.y - terminal.y) < 1e-4 && (point6.route_type === "wire" ? point6.layer : end ? point6.to_layer : point6.from_layer) === terminal.layer;
19087
+ function getAutoroutingPhasePcbTracePaths({
19088
+ group,
19089
+ subcircuit,
19090
+ input,
19091
+ traces,
19092
+ isFanout
19093
+ }) {
19094
+ try {
19095
+ const portsByPcbPortId = new Map(
19096
+ subcircuit.selectAll("port").filter((port) => port.pcb_port_id).map((port) => [port.pcb_port_id, port])
19097
+ );
19098
+ const terminals = input.connections.flatMap(
19099
+ (connection) => connection.pointsToConnect
19100
+ );
19101
+ const routes = traces.map((trace) => {
19102
+ if (trace.route.length < 2 || trace.route.some(
19103
+ (point6) => point6.route_type !== "wire" && point6.route_type !== "via"
19104
+ )) {
19105
+ throw new Error("Only port-anchored wire/via routes can be saved");
19106
+ }
19107
+ return trace.route;
19108
+ });
19109
+ const endpoints = routes.map((route) => [
19110
+ terminals.filter((terminal) => touches(route[0], terminal)),
19111
+ terminals.filter((terminal) => touches(route.at(-1), terminal, true))
19112
+ ]);
19113
+ const degreeByTerminal = /* @__PURE__ */ new Map();
19114
+ for (const routeEndpoints of endpoints) {
19115
+ for (const terminal of new Set(routeEndpoints.flat())) {
19116
+ degreeByTerminal.set(
19117
+ terminal,
19118
+ (degreeByTerminal.get(terminal) ?? 0) + 1
19119
+ );
19120
+ }
19121
+ }
19122
+ const paths = [];
19123
+ const usedPorts = /* @__PURE__ */ new Set();
19124
+ const remainingRoutes = new Set(routes.keys());
19125
+ while (remainingRoutes.size) {
19126
+ let exported = false;
19127
+ for (const routeIndex of remainingRoutes) {
19128
+ for (const reverse of [false, true]) {
19129
+ const candidates = endpoints[routeIndex][reverse ? 1 : 0];
19130
+ if (candidates.length !== 1) continue;
19131
+ const terminal = candidates[0];
19132
+ if (!terminal.pcb_port_id || degreeByTerminal.get(terminal) !== 1)
19133
+ continue;
19134
+ const port = portsByPcbPortId.get(terminal.pcb_port_id);
19135
+ if (!port || usedPorts.has(port)) continue;
19136
+ const selector = terminal.port_selector ?? port.getPortSelector();
19137
+ if (subcircuit.selectOne(selector, { type: "port" }) !== port) {
19138
+ throw new Error(`PCB port selector is not unique: ${selector}`);
19139
+ }
19140
+ const route = reverse ? routes[routeIndex].toReversed().map(
19141
+ (point6) => point6.route_type === "via" ? {
19142
+ ...point6,
19143
+ from_layer: point6.to_layer,
19144
+ to_layer: point6.from_layer
19145
+ } : point6
19146
+ ) : routes[routeIndex];
19147
+ const transform = inverse2(getSavedPcbTracePathTransform(group, port));
19148
+ paths.push(
19149
+ fanoutTracePath2.parse({
19150
+ connection: selector,
19151
+ route: route.map((point6) => ({
19152
+ ...point6,
19153
+ ...applyToPoint28(transform, point6)
19154
+ }))
19155
+ })
19156
+ );
19157
+ usedPorts.add(port);
19158
+ remainingRoutes.delete(routeIndex);
19159
+ for (const endpoint of new Set(endpoints[routeIndex].flat())) {
19160
+ degreeByTerminal.set(endpoint, degreeByTerminal.get(endpoint) - 1);
19161
+ }
19162
+ exported = true;
19163
+ break;
19164
+ }
19165
+ }
19166
+ if (!exported)
19167
+ throw new Error(
19168
+ "Routes contain a junction or endpoint that cannot select a unique PCB port"
19169
+ );
19170
+ }
19171
+ getSavedAutoroutingPhaseTracesFromPaths({
19172
+ group,
19173
+ subcircuit,
19174
+ paths,
19175
+ input,
19176
+ isFanout
19177
+ });
19178
+ return { pcbTracePaths: paths };
19179
+ } catch (error) {
19180
+ return {
19181
+ pcbTracePathsUnavailableReason: error instanceof Error ? error.message : String(error)
19182
+ };
19183
+ }
19184
+ }
19185
+
18878
19186
  // lib/components/primitive-components/Group/Group.ts
18879
19187
  import {
18880
19188
  convertSrjToGraphicsObject,
@@ -51071,7 +51379,7 @@ import {
51071
51379
  midpoint,
51072
51380
  pointToSegmentClosestPoint as pointToSegmentClosestPoint2
51073
51381
  } from "@tscircuit/math-utils";
51074
- import { applyToPoint as applyToPoint28, compose as compose10, scale as scale2, translate as translate8 } from "transformation-matrix";
51382
+ import { applyToPoint as applyToPoint30, compose as compose11, scale as scale2, translate as translate9 } from "transformation-matrix";
51075
51383
 
51076
51384
  // node_modules/@tscircuit/implicit-copper-pour-solver/lib/geometry.ts
51077
51385
  import {
@@ -51087,10 +51395,10 @@ import {
51087
51395
  segmentToSegmentMinDistance
51088
51396
  } from "@tscircuit/math-utils";
51089
51397
  import {
51090
- applyToPoint as applyToPoint27,
51091
- compose as compose9,
51398
+ applyToPoint as applyToPoint29,
51399
+ compose as compose10,
51092
51400
  rotateDEG,
51093
- translate as translate7
51401
+ translate as translate8
51094
51402
  } from "transformation-matrix";
51095
51403
  var rectTransforms = /* @__PURE__ */ new WeakMap();
51096
51404
  var getRectTransforms = (primitive) => {
@@ -51099,13 +51407,13 @@ var getRectTransforms = (primitive) => {
51099
51407
  const transforms = {
51100
51408
  // compose applies the rightmost operation first: move the world point to
51101
51409
  // the rectangle origin, then undo its counter-clockwise rotation.
51102
- toLocal: compose9(
51410
+ toLocal: compose10(
51103
51411
  rotateDEG(-primitive.rotation),
51104
- translate7(-primitive.x, -primitive.y)
51412
+ translate8(-primitive.x, -primitive.y)
51105
51413
  ),
51106
51414
  // Rotate a rectangle-local point before translating it into board space.
51107
- toWorld: compose9(
51108
- translate7(primitive.x, primitive.y),
51415
+ toWorld: compose10(
51416
+ translate8(primitive.x, primitive.y),
51109
51417
  rotateDEG(primitive.rotation)
51110
51418
  )
51111
51419
  };
@@ -51141,7 +51449,7 @@ var distanceToPrimitive = (primitive, px, py) => {
51141
51449
  return distanceToPolygon(point6, primitive.points);
51142
51450
  }
51143
51451
  const { toLocal } = getRectTransforms(primitive);
51144
- return pointToBoxDistance(applyToPoint27(toLocal, point6), {
51452
+ return pointToBoxDistance(applyToPoint29(toLocal, point6), {
51145
51453
  center: { x: 0, y: 0 },
51146
51454
  width: primitive.halfWidth * 2,
51147
51455
  height: primitive.halfHeight * 2
@@ -51185,8 +51493,8 @@ var getClosestPointOnPrimitive = (primitive, point6) => {
51185
51493
  return closestPoint;
51186
51494
  }
51187
51495
  const { toLocal, toWorld } = getRectTransforms(primitive);
51188
- const localPoint = applyToPoint27(toLocal, point6);
51189
- return applyToPoint27(toWorld, {
51496
+ const localPoint = applyToPoint29(toLocal, point6);
51497
+ return applyToPoint29(toWorld, {
51190
51498
  x: clamp(localPoint.x, -primitive.halfWidth, primitive.halfWidth),
51191
51499
  y: clamp(localPoint.y, -primitive.halfHeight, primitive.halfHeight)
51192
51500
  });
@@ -51777,8 +52085,8 @@ var buildPowerPourPolygons = (problem) => {
51777
52085
  1,
51778
52086
  Math.round(problem.minRegionArea / problem.gridPitch ** 2)
51779
52087
  );
51780
- const gridVertexToWorld = compose10(
51781
- translate8(problem.bounds.minX, problem.bounds.minY),
52088
+ const gridVertexToWorld = compose11(
52089
+ translate9(problem.bounds.minX, problem.bounds.minY),
51782
52090
  scale2(problem.gridPitch)
51783
52091
  );
51784
52092
  for (const labeledLayer of problem.labeledLayers) {
@@ -51797,7 +52105,7 @@ var buildPowerPourPolygons = (problem) => {
51797
52105
  }
51798
52106
  const loop = loops[0];
51799
52107
  const points = loop.map(([i, j]) => {
51800
- const point6 = applyToPoint28(gridVertexToWorld, { x: i, y: j });
52108
+ const point6 = applyToPoint30(gridVertexToWorld, { x: i, y: j });
51801
52109
  return {
51802
52110
  x: clamp2(point6.x, problem.bounds.minX, problem.bounds.maxX),
51803
52111
  y: clamp2(point6.y, problem.bounds.minY, problem.bounds.maxY)
@@ -51833,9 +52141,9 @@ import {
51833
52141
  } from "circuit-json-to-connectivity-map";
51834
52142
  import {
51835
52143
  applyToPoints,
51836
- compose as compose11,
52144
+ compose as compose12,
51837
52145
  rotateDEG as rotateDEG2,
51838
- translate as translate9
52146
+ translate as translate10
51839
52147
  } from "transformation-matrix";
51840
52148
  var DEFAULT_GRID_PITCH = 0.25;
51841
52149
  var DEFAULT_TRACE_CLEARANCE = 0.2;
@@ -51863,8 +52171,8 @@ var addPillPrimitive = (primitives, params) => {
51863
52171
  const radius = Math.min(width, height) / 2;
51864
52172
  const axisLength = Math.max(width, height) - radius * 2;
51865
52173
  const halfAxis = axisLength / 2;
51866
- const axisToWorld = compose11(
51867
- translate9(x, y),
52174
+ const axisToWorld = compose12(
52175
+ translate10(x, y),
51868
52176
  rotateDEG2(rotation5 + (height > width ? 90 : 0))
51869
52177
  );
51870
52178
  const [start, end] = applyToPoints(axisToWorld, [
@@ -54003,7 +54311,7 @@ var applyEditEventsToManualEditsFile = ({
54003
54311
 
54004
54312
  // lib/utils/edit-events/apply-edit-events-to-circuit-json.ts
54005
54313
  import { transformPCBElement } from "@tscircuit/circuit-json-util";
54006
- import { translate as translate10 } from "transformation-matrix";
54314
+ import { translate as translate11 } from "transformation-matrix";
54007
54315
 
54008
54316
  // lib/utils/edit-events/apply-trace-hint-edit-event.ts
54009
54317
  import { su as su3 } from "@tscircuit/circuit-json-util";
@@ -54048,7 +54356,7 @@ var applyEditEvents = ({
54048
54356
  );
54049
54357
  const needsMovement = !component || component.center.x !== editEvent.new_center.x || component.center.y !== editEvent.new_center.y;
54050
54358
  if (needsMovement && editEvent.original_center) {
54051
- const mat = translate10(
54359
+ const mat = translate11(
54052
54360
  editEvent.new_center.x - editEvent.original_center.x,
54053
54361
  editEvent.new_center.y - editEvent.original_center.y
54054
54362
  );
@@ -55553,7 +55861,7 @@ import "zod";
55553
55861
 
55554
55862
  // lib/components/primitive-components/TraceHint.ts
55555
55863
  import { traceHintProps } from "@tscircuit/props";
55556
- import { applyToPoint as applyToPoint29 } from "transformation-matrix";
55864
+ import { applyToPoint as applyToPoint31 } from "transformation-matrix";
55557
55865
  var TraceHint = class extends PrimitiveComponent2 {
55558
55866
  matchedPort = null;
55559
55867
  get config() {
@@ -55593,7 +55901,7 @@ var TraceHint = class extends PrimitiveComponent2 {
55593
55901
  const globalTransform = this._computePcbGlobalTransformBeforeLayout();
55594
55902
  return offsets.map(
55595
55903
  (offset) => ({
55596
- ...applyToPoint29(globalTransform, offset),
55904
+ ...applyToPoint31(globalTransform, offset),
55597
55905
  via: offset.via,
55598
55906
  to_layer: offset.to_layer,
55599
55907
  trace_width: offset.trace_width
@@ -57106,7 +57414,7 @@ import {
57106
57414
  transformPCBElements as transformPCBElements2
57107
57415
  } from "@tscircuit/circuit-json-util";
57108
57416
  import { normalizeDegrees as normalizeDegrees7 } from "@tscircuit/math-utils";
57109
- import { compose as compose12, rotate as rotate6, translate as translate11 } from "transformation-matrix";
57417
+ import { compose as compose13, rotate as rotate6, translate as translate12 } from "transformation-matrix";
57110
57418
  var updateCadRotation = ({
57111
57419
  db,
57112
57420
  pcbComponentId,
@@ -57158,11 +57466,11 @@ var applyPackOutput = (group, packOutput, clusterMap, initialPackOutput) => {
57158
57466
  const member = db.pcb_component.get(memberId);
57159
57467
  if (!member) continue;
57160
57468
  const originalCenter2 = member.center;
57161
- const transformMatrix2 = compose12(
57469
+ const transformMatrix2 = compose13(
57162
57470
  group._computePcbGlobalTransformBeforeLayout(),
57163
- translate11(center.x + rotatedRel.x, center.y + rotatedRel.y),
57471
+ translate12(center.x + rotatedRel.x, center.y + rotatedRel.y),
57164
57472
  rotate6(angleRad),
57165
- translate11(-originalCenter2.x, -originalCenter2.y)
57473
+ translate12(-originalCenter2.x, -originalCenter2.y)
57166
57474
  );
57167
57475
  const related = db.toArray().filter(
57168
57476
  (elm) => "pcb_component_id" in elm && elm.pcb_component_id === memberId
@@ -57192,11 +57500,11 @@ var applyPackOutput = (group, packOutput, clusterMap, initialPackOutput) => {
57192
57500
  }
57193
57501
  const originalCenter2 = pcbComponent.center;
57194
57502
  const rotationDegrees2 = ccwRotationDegrees ?? ccwRotationOffset ?? 0;
57195
- const transformMatrix2 = compose12(
57503
+ const transformMatrix2 = compose13(
57196
57504
  group._computePcbGlobalTransformBeforeLayout(),
57197
- translate11(center.x, center.y),
57505
+ translate12(center.x, center.y),
57198
57506
  rotate6(rotationDegrees2 * Math.PI / 180),
57199
- translate11(-originalCenter2.x, -originalCenter2.y)
57507
+ translate12(-originalCenter2.x, -originalCenter2.y)
57200
57508
  );
57201
57509
  const related = db.toArray().filter(
57202
57510
  (elm) => "pcb_component_id" in elm && elm.pcb_component_id === componentId
@@ -57217,11 +57525,11 @@ var applyPackOutput = (group, packOutput, clusterMap, initialPackOutput) => {
57217
57525
  );
57218
57526
  const originalCenter = initialPackedComponent?.center ?? pcbGroup.center;
57219
57527
  const rotationDegrees = ccwRotationDegrees ?? ccwRotationOffset ?? 0;
57220
- const transformMatrix = compose12(
57528
+ const transformMatrix = compose13(
57221
57529
  group._computePcbGlobalTransformBeforeLayout(),
57222
- translate11(center.x, center.y),
57530
+ translate12(center.x, center.y),
57223
57531
  rotate6(rotationDegrees * Math.PI / 180),
57224
- translate11(-originalCenter.x, -originalCenter.y)
57532
+ translate12(-originalCenter.x, -originalCenter.y)
57225
57533
  );
57226
57534
  const relatedElements = db.toArray().filter((elm) => {
57227
57535
  if ("source_group_id" in elm && elm.source_group_id) {
@@ -59599,9 +59907,9 @@ import Debug13 from "debug";
59599
59907
  // lib/components/primitive-components/NetLabel.ts
59600
59908
  import { netLabelProps } from "@tscircuit/props";
59601
59909
  import {
59602
- applyToPoint as applyToPoint30,
59910
+ applyToPoint as applyToPoint32,
59603
59911
  identity as identity7,
59604
- translate as translate12
59912
+ translate as translate13
59605
59913
  } from "transformation-matrix";
59606
59914
  import { calculateElbow as calculateElbow2 } from "calculate-elbow";
59607
59915
  var NetLabel = class extends PrimitiveComponent2 {
@@ -59664,11 +59972,11 @@ var NetLabel = class extends PrimitiveComponent2 {
59664
59972
  const connectedPorts = this._getConnectedPorts();
59665
59973
  if (connectedPorts.length > 0) {
59666
59974
  const portPos = connectedPorts[0]._getGlobalSchematicPositionBeforeLayout();
59667
- const parentCenter = applyToPoint30(
59975
+ const parentCenter = applyToPoint32(
59668
59976
  this.parent?.computeSchematicGlobalTransform?.() ?? identity7(),
59669
59977
  { x: 0, y: 0 }
59670
59978
  );
59671
- return translate12(portPos.x - parentCenter.x, portPos.y - parentCenter.y);
59979
+ return translate13(portPos.x - parentCenter.x, portPos.y - parentCenter.y);
59672
59980
  }
59673
59981
  }
59674
59982
  return super.computeSchematicPropsTransform();
@@ -63205,190 +63513,8 @@ var Group_getFanoutPourNetMap = (group, routingPhasePlans) => {
63205
63513
  // lib/components/primitive-components/Group/Group_getRoutingPhasePlans.ts
63206
63514
  import { getBoundsFromPoints as getBoundsFromPoints8 } from "@tscircuit/math-utils";
63207
63515
 
63208
- // lib/components/primitive-components/Group/get-saved-autorouting-phase-traces.ts
63209
- import { applyToPoint as applyToPoint31, compose as compose13, translate as translate13 } from "transformation-matrix";
63210
- var touchesEndpoint = (point6, endpoint) => Math.hypot(point6.x - endpoint.x, point6.y - endpoint.y) < 1e-4 && point6.layer === endpoint.layer;
63211
- function getSavedAutoroutingPhaseTraces(phase, input, isFanout) {
63212
- const group = phase.getGroup();
63213
- const transformBeforeLayout = group._computePcbGlobalTransformBeforeLayout();
63214
- const boardLayers = getViaBoardLayers(input.layerCount);
63215
- const remainingPointsByConnection = new Map(
63216
- input.connections.map((connection) => [
63217
- connection,
63218
- [...connection.pointsToConnect]
63219
- ])
63220
- );
63221
- const coveredConnections = /* @__PURE__ */ new Set();
63222
- const savedPorts = /* @__PURE__ */ new Set();
63223
- const traces = [];
63224
- for (const [pathIndex, path] of (phase._parsedProps.pcbTracePaths ?? []).entries()) {
63225
- const port = phase.getSubcircuit().selectOne(path.connection, { type: "port" });
63226
- if (!port)
63227
- throw new Error(
63228
- `Saved phase path "${path.connection}" must select a PCB port`
63229
- );
63230
- if (savedPorts.has(port))
63231
- throw new Error(`Duplicate saved phase path for "${path.connection}"`);
63232
- savedPorts.add(port);
63233
- const connections = input.connections.filter(
63234
- (connection2) => connection2.pointsToConnect.some(
63235
- (point6) => point6.pcb_port_id === port.pcb_port_id
63236
- )
63237
- );
63238
- if (connections.length !== 1) {
63239
- throw new Error(
63240
- `Saved phase path "${path.connection}" must select exactly one connection in this phase`
63241
- );
63242
- }
63243
- const connection = connections[0];
63244
- const remainingPoints = remainingPointsByConnection.get(connection);
63245
- const startIndex = remainingPoints.findIndex(
63246
- (point6) => point6.pcb_port_id === port.pcb_port_id
63247
- );
63248
- if (startIndex < 0)
63249
- throw new Error(
63250
- `Saved phase path "${path.connection}" starts at an endpoint already joined by another path`
63251
- );
63252
- const portBeforeLayout = port._getGlobalPcbPositionBeforeLayout();
63253
- const portAfterLayout = port._getGlobalPcbPositionAfterLayout();
63254
- const transform = compose13(
63255
- translate13(
63256
- portAfterLayout.x - portBeforeLayout.x,
63257
- portAfterLayout.y - portBeforeLayout.y
63258
- ),
63259
- transformBeforeLayout
63260
- );
63261
- const route = path.route.map((point6) => ({
63262
- ...point6,
63263
- ...applyToPoint31(transform, point6)
63264
- }));
63265
- for (const point6 of route) {
63266
- const layers = point6.route_type === "wire" ? [point6.layer] : [point6.from_layer, point6.to_layer];
63267
- if (layers.some((layer) => !boardLayers.includes(layer))) {
63268
- throw new Error(
63269
- `Saved phase path "${path.connection}" uses a layer unavailable on this board`
63270
- );
63271
- }
63272
- }
63273
- const first = route[0];
63274
- const last = route.at(-1);
63275
- const firstLayer = first.route_type === "wire" ? first.layer : first.from_layer;
63276
- const lastLayer = last.route_type === "wire" ? last.layer : last.to_layer;
63277
- if (!touchesEndpoint(remainingPoints[startIndex], {
63278
- ...first,
63279
- layer: firstLayer
63280
- })) {
63281
- throw new Error(
63282
- `Saved phase path "${path.connection}" must start at its PCB port on an available layer`
63283
- );
63284
- }
63285
- const endIndex = remainingPoints.findIndex(
63286
- (point6, index) => index !== startIndex && touchesEndpoint(point6, { ...last, layer: lastLayer })
63287
- );
63288
- if (!input.allowViaInPad && (first.route_type === "via" || last.route_type === "via" && endIndex >= 0)) {
63289
- throw new Error(
63290
- `Saved phase path "${path.connection}" has a via at a pad; enable allowViaInPad`
63291
- );
63292
- }
63293
- const pcbTraceId = `saved_phase_${group.pcb_group_id}_${phase._parsedProps.phaseIndex ?? "default"}_${pathIndex}`;
63294
- if (endIndex < 0 && !isFanout) {
63295
- throw new Error(
63296
- `Saved phase path "${path.connection}" must end at another connection endpoint; use autorouter="fanout" for saved escapes`
63297
- );
63298
- }
63299
- if (endIndex >= 0) {
63300
- remainingPoints.splice(startIndex, 1);
63301
- } else {
63302
- remainingPoints[startIndex] = {
63303
- x: last.x,
63304
- y: last.y,
63305
- layer: lastLayer,
63306
- pointId: `${pcbTraceId}_exit`
63307
- };
63308
- }
63309
- const width = route.find((point6) => point6.route_type === "wire")?.width ?? input.minTraceWidth;
63310
- const routeWithViaContacts = route.flatMap(
63311
- (point6) => point6.route_type === "via" ? [
63312
- {
63313
- route_type: "wire",
63314
- x: point6.x,
63315
- y: point6.y,
63316
- layer: point6.from_layer,
63317
- width
63318
- },
63319
- point6,
63320
- {
63321
- route_type: "wire",
63322
- x: point6.x,
63323
- y: point6.y,
63324
- layer: point6.to_layer,
63325
- width
63326
- }
63327
- ] : [point6]
63328
- );
63329
- if (last.route_type === "via") {
63330
- routeWithViaContacts.push({
63331
- route_type: "wire",
63332
- x: last.x,
63333
- y: last.y,
63334
- layer: last.to_layer,
63335
- width
63336
- });
63337
- }
63338
- coveredConnections.add(connection);
63339
- traces.push({
63340
- type: "pcb_trace",
63341
- pcb_trace_id: pcbTraceId,
63342
- connection_name: connection.name,
63343
- connectsTo: [
63344
- connection.source_trace_id,
63345
- ...connection.pointsToConnect.map((point6) => point6.pointId)
63346
- ].filter((id) => Boolean(id)),
63347
- route: routeWithViaContacts
63348
- });
63349
- }
63350
- for (const connection of input.connections) {
63351
- if (!coveredConnections.has(connection)) {
63352
- throw new Error(
63353
- `pcbTracePaths must cover every connection in the phase; missing: ${connection.name}`
63354
- );
63355
- }
63356
- if (!isFanout && remainingPointsByConnection.get(connection).length > 1) {
63357
- throw new Error(
63358
- `Saved phase paths for "${connection.name}" must connect every endpoint; use autorouter="fanout" for saved escapes`
63359
- );
63360
- }
63361
- }
63362
- const remainingConnections = input.connections.flatMap((connection) => {
63363
- const pointsToConnect = remainingPointsByConnection.get(connection);
63364
- return pointsToConnect.length > 1 ? [{ ...connection, pointsToConnect }] : [];
63365
- });
63366
- const remainingConnectionNames = new Set(
63367
- remainingConnections.map((connection) => connection.name)
63368
- );
63369
- return {
63370
- traces,
63371
- outputSimpleRouteJson: isFanout ? {
63372
- ...input,
63373
- connections: remainingConnections,
63374
- buses: input.buses?.map((bus) => ({
63375
- ...bus,
63376
- connectionNames: bus.connectionNames.filter(
63377
- (name) => remainingConnectionNames.has(name)
63378
- )
63379
- })).filter((bus) => bus.connectionNames.length > 0),
63380
- differentialPairs: input.differentialPairs?.filter(
63381
- (pair) => pair.connectionNames.every(
63382
- (name) => remainingConnectionNames.has(name)
63383
- )
63384
- ),
63385
- traces: [...input.traces ?? [], ...traces]
63386
- } : void 0
63387
- };
63388
- }
63389
-
63390
63516
  // lib/components/primitive-components/Breakout/get-saved-fanout-traces.ts
63391
- import { applyToPoint as applyToPoint32, compose as compose14, translate as translate14 } from "transformation-matrix";
63517
+ import { applyToPoint as applyToPoint33, compose as compose14, translate as translate14 } from "transformation-matrix";
63392
63518
 
63393
63519
  // lib/components/primitive-components/BreakoutPoint.ts
63394
63520
  import { breakoutPointProps } from "@tscircuit/props";
@@ -63556,9 +63682,9 @@ function getSavedFanoutTraces(breakout, input) {
63556
63682
  exit._computePcbGlobalTransformBeforeLayout(),
63557
63683
  translate14(-localExit.x, -localExit.y)
63558
63684
  );
63559
- const originalExit = applyToPoint32(transform, localExit);
63685
+ const originalExit = applyToPoint33(transform, localExit);
63560
63686
  const route = path.route.map((point6) => {
63561
- const position = applyToPoint32(transform, point6);
63687
+ const position = applyToPoint33(transform, point6);
63562
63688
  return {
63563
63689
  ...point6,
63564
63690
  x: position.x + pcbExit.x - originalExit.x,
@@ -63908,9 +64034,10 @@ function Group_getRoutingPhasePlans(group) {
63908
64034
  for (const phase of group.selectAll(
63909
64035
  "autoroutingphase"
63910
64036
  )) {
63911
- if (phase._parsedProps.pcbTracePaths === void 0) continue;
63912
64037
  const plan = plansByPhaseIndex.get(phase._parsedProps.phaseIndex ?? null);
63913
64038
  if (!plan) continue;
64039
+ plan.autoroutingPhase = phase;
64040
+ if (phase._parsedProps.pcbTracePaths === void 0) continue;
63914
64041
  const config = plan.autorouter !== void 0 ? getPresetAutoroutingConfig(plan.autorouter, group.root?.platform) : group._getAutorouterConfig();
63915
64042
  const isFanout = ["fanout", "single_layer_fanout"].includes(
63916
64043
  config.preset ?? ""
@@ -64031,7 +64158,7 @@ function Group_getRoutingPhasePlans(group) {
64031
64158
  var package_default = {
64032
64159
  name: "@tscircuit/core",
64033
64160
  type: "module",
64034
- version: "0.0.1998",
64161
+ version: "0.0.1999",
64035
64162
  types: "dist/index.d.ts",
64036
64163
  main: "dist/index.js",
64037
64164
  module: "dist/index.js",
@@ -66446,7 +66573,17 @@ var Group5 = class extends NormalComponent {
66446
66573
  }
66447
66574
  });
66448
66575
  }
66576
+ const savedPhasePaths = getAutoroutingPhasePcbTracePaths({
66577
+ group: routingPhasePlan.autoroutingPhase?.getGroup() ?? this,
66578
+ subcircuit: this,
66579
+ input: simpleRouteJson,
66580
+ traces,
66581
+ isFanout: ["fanout", "single_layer_fanout"].includes(
66582
+ phaseAutorouterConfig.preset ?? ""
66583
+ )
66584
+ });
66449
66585
  this.root?.emit("autorouting:end", {
66586
+ ...savedPhasePaths,
66450
66587
  type: "autorouting:end",
66451
66588
  subcircuit_id: this.subcircuit_id,
66452
66589
  componentDisplayName: this.getString(),
@@ -67335,7 +67472,7 @@ function inflateSourceInductor(sourceElm, inflatorContext) {
67335
67472
  import { ledProps } from "@tscircuit/props";
67336
67473
 
67337
67474
  // lib/components/normal-components/Led_addPolarityFabricationSymbol.ts
67338
- import { applyToPoint as applyToPoint33, compose as compose15, rotate as rotate7, translate as translate15 } from "transformation-matrix";
67475
+ import { applyToPoint as applyToPoint34, compose as compose15, rotate as rotate7, translate as translate15 } from "transformation-matrix";
67339
67476
  var generatedNotes = /* @__PURE__ */ new WeakMap();
67340
67477
  var getPolarity2 = (port) => {
67341
67478
  const hints = [port.name, ...port.port_hints ?? []].map(
@@ -67380,7 +67517,7 @@ var Led_addPolarityFabricationSymbol = (led) => {
67380
67517
  translate15((a.x + k.x) / 2, (a.y + k.y) / 2),
67381
67518
  rotate7(angle)
67382
67519
  );
67383
- const point6 = (x, y) => applyToPoint33(frame, { x, y });
67520
+ const point6 = (x, y) => applyToPoint34(frame, { x, y });
67384
67521
  const common = {
67385
67522
  pcb_component_id: pcb.pcb_component_id,
67386
67523
  subcircuit_id: led.getSubcircuit()?.subcircuit_id ?? void 0,
@@ -72493,7 +72630,7 @@ var AutoroutingPhase = class extends PrimitiveComponent2 {
72493
72630
 
72494
72631
  // lib/components/primitive-components/FabricationNoteDimension.ts
72495
72632
  import { fabricationNoteDimensionProps } from "@tscircuit/props";
72496
- import { applyToPoint as applyToPoint34 } from "transformation-matrix";
72633
+ import { applyToPoint as applyToPoint35 } from "transformation-matrix";
72497
72634
  var FabricationNoteDimension = class extends PrimitiveComponent2 {
72498
72635
  fabrication_note_dimension_id = null;
72499
72636
  isPcbPrimitive = true;
@@ -72512,13 +72649,13 @@ var FabricationNoteDimension = class extends PrimitiveComponent2 {
72512
72649
  this.renderError(
72513
72650
  `FabricationNoteDimension could not find selector "${input}"`
72514
72651
  );
72515
- return applyToPoint34(transform, { x: 0, y: 0 });
72652
+ return applyToPoint35(transform, { x: 0, y: 0 });
72516
72653
  }
72517
72654
  return target._getGlobalPcbPositionBeforeLayout();
72518
72655
  }
72519
72656
  const numericX = typeof input.x === "string" ? parseFloat(input.x) : input.x;
72520
72657
  const numericY = typeof input.y === "string" ? parseFloat(input.y) : input.y;
72521
- return applyToPoint34(transform, { x: numericX, y: numericY });
72658
+ return applyToPoint35(transform, { x: numericX, y: numericY });
72522
72659
  }
72523
72660
  doInitialPcbPrimitiveRender() {
72524
72661
  if (this.root?.pcbDisabled) return;
@@ -72613,7 +72750,7 @@ var FabricationNoteDimension = class extends PrimitiveComponent2 {
72613
72750
 
72614
72751
  // lib/components/primitive-components/PcbNoteDimension.ts
72615
72752
  import { pcbNoteDimensionProps } from "@tscircuit/props";
72616
- import { applyToPoint as applyToPoint35 } from "transformation-matrix";
72753
+ import { applyToPoint as applyToPoint36 } from "transformation-matrix";
72617
72754
  var PcbNoteDimension = class extends PrimitiveComponent2 {
72618
72755
  pcb_note_dimension_id = null;
72619
72756
  isPcbPrimitive = true;
@@ -72630,7 +72767,7 @@ var PcbNoteDimension = class extends PrimitiveComponent2 {
72630
72767
  );
72631
72768
  if (!target) {
72632
72769
  this.renderError(`PcbNoteDimension could not find selector "${input}"`);
72633
- return applyToPoint35(transform, { x: 0, y: 0 });
72770
+ return applyToPoint36(transform, { x: 0, y: 0 });
72634
72771
  }
72635
72772
  const targetPcbComponentId = target.pcb_component_id;
72636
72773
  const root = this.root;
@@ -72647,7 +72784,7 @@ var PcbNoteDimension = class extends PrimitiveComponent2 {
72647
72784
  }
72648
72785
  const numericX = typeof input.x === "string" ? parseFloat(input.x) : input.x;
72649
72786
  const numericY = typeof input.y === "string" ? parseFloat(input.y) : input.y;
72650
- return applyToPoint35(transform, { x: numericX, y: numericY });
72787
+ return applyToPoint36(transform, { x: numericX, y: numericY });
72651
72788
  }
72652
72789
  doInitialPcbPrimitiveRender() {
72653
72790
  if (this.root?.pcbDisabled) return;
@@ -75398,7 +75535,7 @@ import {
75398
75535
  getTransformedSvgPathRoutes,
75399
75536
  loadImageSource
75400
75537
  } from "@tscircuit/image-utils";
75401
- import { applyToPoint as applyToPoint36 } from "transformation-matrix";
75538
+ import { applyToPoint as applyToPoint37 } from "transformation-matrix";
75402
75539
  var SilkscreenGraphic = class extends PrimitiveComponent2 {
75403
75540
  pcb_silkscreen_graphic_id = null;
75404
75541
  pcb_silkscreen_graphic_ids = [];
@@ -75500,7 +75637,7 @@ var SilkscreenGraphic = class extends PrimitiveComponent2 {
75500
75637
  { x: halfWidth, y: -halfHeight },
75501
75638
  { x: -halfWidth, y: -halfHeight }
75502
75639
  ]).map(
75503
- (point6) => applyToPoint36(transform, point6)
75640
+ (point6) => applyToPoint37(transform, point6)
75504
75641
  )
75505
75642
  },
75506
75643
  inner_rings: []
@@ -78444,7 +78581,7 @@ var SpiceModel = class extends PrimitiveComponent2 {
78444
78581
 
78445
78582
  // lib/components/primitive-components/PcbBend.ts
78446
78583
  import { pcbBendProps } from "@tscircuit/props";
78447
- import { applyToPoint as applyToPoint37 } from "transformation-matrix";
78584
+ import { applyToPoint as applyToPoint38 } from "transformation-matrix";
78448
78585
 
78449
78586
  // lib/components/primitive-components/getPcbFlexBoardTransform.ts
78450
78587
  import { compose as compose18, translate as translate18 } from "transformation-matrix";
@@ -78477,8 +78614,8 @@ var PcbBend = class extends PrimitiveComponent2 {
78477
78614
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
78478
78615
  subcircuit_id: this.getSubcircuit().subcircuit_id ?? void 0,
78479
78616
  name: props.name,
78480
- start: applyToPoint37(transform, { x: props.x1, y: props.y1 }),
78481
- end: applyToPoint37(transform, { x: props.x2, y: props.y2 }),
78617
+ start: applyToPoint38(transform, { x: props.x1, y: props.y1 }),
78618
+ end: applyToPoint38(transform, { x: props.x2, y: props.y2 }),
78482
78619
  bend_angle: props.bendAngle,
78483
78620
  bend_radius: props.bendRadius,
78484
78621
  bend_side: props.bendSide
@@ -78493,7 +78630,7 @@ var PcbBend = class extends PrimitiveComponent2 {
78493
78630
 
78494
78631
  // lib/components/primitive-components/PcbStiffener.ts
78495
78632
  import { pcbStiffenerProps } from "@tscircuit/props";
78496
- import { applyToPoint as applyToPoint38, decomposeTSR as decomposeTSR10 } from "transformation-matrix";
78633
+ import { applyToPoint as applyToPoint39, decomposeTSR as decomposeTSR10 } from "transformation-matrix";
78497
78634
  var PcbStiffener = class extends PrimitiveComponent2 {
78498
78635
  pcb_stiffener_id = null;
78499
78636
  get config() {
@@ -78516,14 +78653,14 @@ var PcbStiffener = class extends PrimitiveComponent2 {
78516
78653
  };
78517
78654
  const geometry = props.shape === "rect" ? {
78518
78655
  shape: "rect",
78519
- center: applyToPoint38(transform, { x: 0, y: 0 }),
78656
+ center: applyToPoint39(transform, { x: 0, y: 0 }),
78520
78657
  rotation: decomposeTSR10(transform).rotation.angle * 180 / Math.PI,
78521
78658
  width: props.width,
78522
78659
  height: props.height
78523
78660
  } : {
78524
78661
  shape: "polygon",
78525
78662
  outline: props.outline.map(
78526
- (point6) => applyToPoint38(transform, point6)
78663
+ (point6) => applyToPoint39(transform, point6)
78527
78664
  )
78528
78665
  };
78529
78666
  this.pcb_stiffener_id = db.pcb_stiffener.insert({
@@ -78825,7 +78962,7 @@ extendCatalogue({
78825
78962
  });
78826
78963
 
78827
78964
  // lib/index.ts
78828
- import { fanoutTracePath } from "@tscircuit/props";
78965
+ import { fanoutTracePath as fanoutTracePath3 } from "@tscircuit/props";
78829
78966
  export {
78830
78967
  Ammeter,
78831
78968
  AnalogAcSweepSimulation,
@@ -78955,7 +79092,7 @@ export {
78955
79092
  createElement2 as createElement,
78956
79093
  createUseComponent,
78957
79094
  enclosure,
78958
- fanoutTracePath,
79095
+ fanoutTracePath3 as fanoutTracePath,
78959
79096
  getPhaseTimingsFromRenderEvents,
78960
79097
  getSimpleRouteJsonFromCircuitJson,
78961
79098
  kicadFootprintStrings,