@tscircuit/core 0.0.1805 → 0.0.1806

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 (2) hide show
  1. package/dist/index.js +86 -26
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -24036,9 +24036,28 @@ function matchComponent(params) {
24036
24036
  })
24037
24037
  );
24038
24038
  if (entries.some((entry) => entry.candidates.length === 0)) return null;
24039
- const assignedCandidates = /* @__PURE__ */ new Map();
24039
+ const forcedCandidates = entries.flatMap(
24040
+ (entry) => entry.candidates.length === 1 ? [entry.candidates[0]] : []
24041
+ );
24042
+ for (let candidateIndex = 0; candidateIndex < forcedCandidates.length; candidateIndex++) {
24043
+ const candidate = forcedCandidates[candidateIndex];
24044
+ for (let previousIndex = 0; previousIndex < candidateIndex; previousIndex++) {
24045
+ if (!candidatesAreMutuallyClear({
24046
+ first: candidate,
24047
+ second: forcedCandidates[previousIndex],
24048
+ rules
24049
+ })) {
24050
+ return null;
24051
+ }
24052
+ }
24053
+ }
24054
+ const assignedCandidates = new Map(
24055
+ forcedCandidates.map((candidate) => [candidate.connectionIndex, candidate])
24056
+ );
24040
24057
  const remaining = new Set(
24041
- entries.map((entry) => entry.connection.preparedConnection.connectionIndex)
24058
+ entries.flatMap(
24059
+ (entry) => entry.candidates.length > 1 ? [entry.connection.preparedConnection.connectionIndex] : []
24060
+ )
24042
24061
  );
24043
24062
  const entryByConnectionIndex = new Map(
24044
24063
  entries.map((entry) => [
@@ -24046,6 +24065,14 @@ function matchComponent(params) {
24046
24065
  entry
24047
24066
  ])
24048
24067
  );
24068
+ if (remaining.size === 0) {
24069
+ return new Map(
24070
+ [...assignedCandidates.entries()].map(([connectionIndex, candidate]) => [
24071
+ connectionIndex,
24072
+ { ...candidate.point }
24073
+ ])
24074
+ );
24075
+ }
24049
24076
  const getViableCandidates = (entry) => entry.candidates.filter(
24050
24077
  (candidate) => [...assignedCandidates.values()].every(
24051
24078
  (assignedCandidate) => candidatesAreMutuallyClear({
@@ -28276,25 +28303,48 @@ function busUsesCoordinatedWinding(bus) {
28276
28303
  );
28277
28304
  }
28278
28305
  function shouldUseJointBoundaryViaReservation(boundaryBusConnectionCounts) {
28279
- return boundaryBusConnectionCounts.length === 5 || boundaryBusConnectionCounts.length === 6 || boundaryBusConnectionCounts.length === 7 || boundaryBusConnectionCounts.length === 4 && new Set(boundaryBusConnectionCounts).size > 1;
28306
+ return boundaryBusConnectionCounts.length === 5 || boundaryBusConnectionCounts.length === 6 || boundaryBusConnectionCounts.length === 7 || boundaryBusConnectionCounts.length === 8 || boundaryBusConnectionCounts.length === 4 && new Set(boundaryBusConnectionCounts).size > 1;
28280
28307
  }
28281
28308
  function shouldDeferSingletonBoundaryViaReservation(boundaryBusConnectionCounts) {
28282
- return (boundaryBusConnectionCounts.length === 5 || boundaryBusConnectionCounts.length === 6 || boundaryBusConnectionCounts.length === 7) && boundaryBusConnectionCounts.filter((count) => count === 1).length === 1;
28309
+ const boundaryBusCount = boundaryBusConnectionCounts.length;
28310
+ const singletonBusCount = boundaryBusConnectionCounts.filter(
28311
+ (count) => count === 1
28312
+ ).length;
28313
+ return (boundaryBusCount === 5 || boundaryBusCount === 6 || boundaryBusCount === 7) && singletonBusCount === 1 || boundaryBusCount === 8 && (singletonBusCount === 1 || singletonBusCount === 2);
28283
28314
  }
28284
28315
  function shouldSearchAdditionalBoundaryRouteTopologies(params) {
28285
- if (params.boundaryBusCount === 5 || params.boundaryBusCount > 7) {
28316
+ if (params.boundaryBusCount === 5 || params.boundaryBusCount > 8) {
28286
28317
  return false;
28287
28318
  }
28288
- if (params.boundaryBusCount === 6 || params.boundaryBusCount === 7) {
28319
+ if (params.boundaryBusCount === 6 || params.boundaryBusCount === 7 || params.boundaryBusCount === 8) {
28289
28320
  return params.connectionCount > 2 && params.rawSkew - params.maximumSkew > Math.max(1, params.maximumSkew * 0.5);
28290
28321
  }
28291
28322
  return params.rawSkew - params.maximumSkew > Math.max(1, params.maximumSkew * 0.25);
28292
28323
  }
28293
- function getDenseSevenBusPairRoutingPriorityKeys(params) {
28324
+ function getDenseSingletonBoundaryGeometry(bus) {
28325
+ const connection = bus.connections[0];
28326
+ const target = connection?.exitTargetPoint;
28327
+ let targetProjection = 0;
28328
+ if (connection && target) {
28329
+ const deltaX = target.x - connection.sourcePoint.x;
28330
+ const deltaY = target.y - connection.sourcePoint.y;
28331
+ targetProjection = bus.direction === "right" ? deltaX : bus.direction === "left" ? -deltaX : bus.direction === "up" ? deltaY : -deltaY;
28332
+ }
28333
+ return {
28334
+ isCorner: Boolean(getCornerBandSide(bus.exitEdge, bus.preferredExit)),
28335
+ targetProjection
28336
+ };
28337
+ }
28338
+ function compareDenseSingletonBoundaryDeferralPriority(first, second) {
28339
+ const firstGeometry = getDenseSingletonBoundaryGeometry(first);
28340
+ const secondGeometry = getDenseSingletonBoundaryGeometry(second);
28341
+ return Number(firstGeometry.isCorner) - Number(secondGeometry.isCorner) || (firstGeometry.isCorner && secondGeometry.isCorner ? Number(firstGeometry.targetProjection > 0) - Number(secondGeometry.targetProjection > 0) : 0) || first.busId.localeCompare(second.busId);
28342
+ }
28343
+ function getDenseBoundaryPairRoutingPriorityKeys(params) {
28294
28344
  const { pairBuses } = params;
28295
28345
  const firstBus = pairBuses[0];
28296
28346
  const firstSourceLayer = firstBus?.connections[0]?.sourceLayer;
28297
- if (params.boundaryBusCount !== 7 || pairBuses.length !== 3 || firstBus === void 0 || firstBus.exitEdge === void 0 || firstBus.assignedLayer === void 0 || firstSourceLayer === void 0 || pairBuses.some(
28347
+ if (params.boundaryBusCount !== 7 && params.boundaryBusCount !== 8 || pairBuses.length !== 3 || firstBus === void 0 || firstBus.exitEdge === void 0 || firstBus.assignedLayer === void 0 || firstSourceLayer === void 0 || pairBuses.some(
28298
28348
  (bus) => bus.connections.length !== 2 || bus.componentId !== firstBus.componentId || bus.exitEdge !== firstBus.exitEdge || bus.assignedLayer !== firstBus.assignedLayer || bus.connections.some((connection) => {
28299
28349
  const exitTarget = connection.exitTargetPoint;
28300
28350
  return connection.sourceLayer !== firstSourceLayer || exitTarget?.layer !== firstBus.assignedLayer || !Number.isFinite(connection.sourcePoint.x) || !Number.isFinite(connection.sourcePoint.y) || !Number.isFinite(exitTarget?.x) || !Number.isFinite(exitTarget?.y);
@@ -28302,15 +28352,17 @@ function getDenseSevenBusPairRoutingPriorityKeys(params) {
28302
28352
  )) {
28303
28353
  return null;
28304
28354
  }
28305
- const getMeanSourceToExitTargetDistance = (bus) => bus.connections.reduce((total, connection) => {
28306
- const exitTarget = connection.exitTargetPoint;
28307
- return total + Math.hypot(
28308
- exitTarget.x - connection.sourcePoint.x,
28309
- exitTarget.y - connection.sourcePoint.y
28310
- );
28311
- }, 0) / bus.connections.length;
28355
+ const getMaximumSourceToExitTargetDistance = (bus) => Math.max(
28356
+ ...bus.connections.map((connection) => {
28357
+ const exitTarget = connection.exitTargetPoint;
28358
+ return Math.hypot(
28359
+ exitTarget.x - connection.sourcePoint.x,
28360
+ exitTarget.y - connection.sourcePoint.y
28361
+ );
28362
+ })
28363
+ );
28312
28364
  return pairBuses.map(
28313
- (bus) => Number(getMeanSourceToExitTargetDistance(bus).toFixed(9))
28365
+ (bus) => Number(getMaximumSourceToExitTargetDistance(bus).toFixed(9))
28314
28366
  );
28315
28367
  }
28316
28368
  function getCandidateEscapeLayersForBus(params) {
@@ -28535,7 +28587,7 @@ var FanoutSolver = class extends BaseSolver {
28535
28587
  const twoConnectionBoundaryBuses = unsortedBoundaryBuses.filter(
28536
28588
  (bus) => bus.connections.length === 2
28537
28589
  );
28538
- const pairRoutingPriorityKeys = getDenseSevenBusPairRoutingPriorityKeys({
28590
+ const pairRoutingPriorityKeys = getDenseBoundaryPairRoutingPriorityKeys({
28539
28591
  boundaryBusCount: unsortedBoundaryBuses.length,
28540
28592
  pairBuses: twoConnectionBoundaryBuses.map((bus) => ({
28541
28593
  ...bus,
@@ -28588,7 +28640,7 @@ var FanoutSolver = class extends BaseSolver {
28588
28640
  }
28589
28641
  const layerDifference = this.config.layerNames.indexOf(firstLayer ?? "") - this.config.layerNames.indexOf(secondLayer ?? "");
28590
28642
  if (layerDifference !== 0) return -layerDifference;
28591
- if (unsortedBoundaryBuses.length !== 6 && unsortedBoundaryBuses.length !== 7) {
28643
+ if (unsortedBoundaryBuses.length !== 6 && unsortedBoundaryBuses.length !== 7 && unsortedBoundaryBuses.length !== 8) {
28592
28644
  return 0;
28593
28645
  }
28594
28646
  return first.busId.localeCompare(second.busId);
@@ -28596,7 +28648,7 @@ var FanoutSolver = class extends BaseSolver {
28596
28648
  const planeBuses = this.preparedBuses.filter(
28597
28649
  (bus) => bus.termination.type === "plane"
28598
28650
  );
28599
- if (boundaryBuses.length === 0 || boundaryBuses.length > 7 || planeBuses.length < 8 || boundaryBuses.some((bus) => !busUsesCoordinatedWinding(bus)) || planeBuses.some((bus) => bus.connections.length !== 1) || boundaryBuses.length + planeBuses.length !== params.busesInRoutingOrder.length) {
28651
+ if (boundaryBuses.length === 0 || boundaryBuses.length > 8 || planeBuses.length < 8 || boundaryBuses.some((bus) => !busUsesCoordinatedWinding(bus)) || planeBuses.some((bus) => bus.connections.length !== 1) || boundaryBuses.length + planeBuses.length !== params.busesInRoutingOrder.length) {
28600
28652
  return null;
28601
28653
  }
28602
28654
  const connectionNameByIndex = new Map(
@@ -28606,13 +28658,17 @@ var FanoutSolver = class extends BaseSolver {
28606
28658
  )
28607
28659
  )
28608
28660
  );
28661
+ const singletonBoundaryBusCount = boundaryBuses.filter(
28662
+ (bus) => bus.connections.length === 1
28663
+ ).length;
28664
+ const useGeometryAwareSingletonOutwardPreference = boundaryBuses.length === 8 && singletonBoundaryBusCount === 2;
28609
28665
  const preferredBoundaryPerpendicularSideByBusId = new Map(
28610
28666
  boundaryBuses.map((bus) => [bus.busId, 1])
28611
28667
  );
28612
28668
  const preferBoundaryOutwardByBusId = new Map(
28613
28669
  boundaryBuses.map((bus) => [
28614
28670
  bus.busId,
28615
- getExitEdgeForDirection(bus.direction) !== bus.exitEdge
28671
+ useGeometryAwareSingletonOutwardPreference && bus.connections.length === 1 && getCornerBandSide(bus.exitEdge, bus.preferredExit) ? getDenseSingletonBoundaryGeometry(bus).targetProjection > 0 : getExitEdgeForDirection(bus.direction) !== bus.exitEdge
28616
28672
  ])
28617
28673
  );
28618
28674
  const canShareCopper = (firstConnectionIndex, secondConnectionIndex) => {
@@ -28632,10 +28688,14 @@ var FanoutSolver = class extends BaseSolver {
28632
28688
  const boundaryBusConnectionCounts = boundaryBuses.map(
28633
28689
  (bus) => bus.connections.length
28634
28690
  );
28635
- const provisionalSingletonBus = shouldDeferSingletonBoundaryViaReservation(
28636
- boundaryBusConnectionCounts
28637
- ) ? boundaryBuses.find((bus) => bus.connections.length === 1) : void 0;
28638
- const initiallyMatchedBoundaryBuses = provisionalSingletonBus ? boundaryBuses.filter((bus) => bus !== provisionalSingletonBus) : boundaryBuses;
28691
+ const singletonBoundaryBuses = boundaryBuses.filter(
28692
+ (bus) => bus.connections.length === 1
28693
+ );
28694
+ const provisionalSingletonBuses = shouldDeferSingletonBoundaryViaReservation(boundaryBusConnectionCounts) ? singletonBoundaryBuses.toSorted(compareDenseSingletonBoundaryDeferralPriority).slice(0, 1) : [];
28695
+ const provisionalSingletonBusSet = new Set(provisionalSingletonBuses);
28696
+ const initiallyMatchedBoundaryBuses = boundaryBuses.filter(
28697
+ (bus) => !provisionalSingletonBusSet.has(bus)
28698
+ );
28639
28699
  const jointViaPoints = useJointBoundaryViaReservation ? matchComponentDogboneViaSites(
28640
28700
  [...planeBuses, ...initiallyMatchedBoundaryBuses],
28641
28701
  {
@@ -41920,7 +41980,7 @@ function Group_getRoutingPhasePlans(group) {
41920
41980
  var package_default = {
41921
41981
  name: "@tscircuit/core",
41922
41982
  type: "module",
41923
- version: "0.0.1804",
41983
+ version: "0.0.1805",
41924
41984
  types: "dist/index.d.ts",
41925
41985
  main: "dist/index.js",
41926
41986
  module: "dist/index.js",
@@ -41960,7 +42020,7 @@ var package_default = {
41960
42020
  "@tscircuit/common": "^0.0.20",
41961
42021
  "@tscircuit/copper-pour-solver": "^0.0.51",
41962
42022
  "@tscircuit/create-fdm-enclosure": "0.0.4",
41963
- "@tscircuit/fanout-solver": "0.0.45",
42023
+ "@tscircuit/fanout-solver": "0.0.46",
41964
42024
  "@tscircuit/footprinter": "^0.0.426",
41965
42025
  "@tscircuit/image-utils": "^0.0.8",
41966
42026
  "@tscircuit/implicit-copper-pour-solver": "github:tscircuit/implicit-copper-pour-solver#47f930139fe969550e049aa7fb741bbcb1f08569",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1805",
4
+ "version": "0.0.1806",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -41,7 +41,7 @@
41
41
  "@tscircuit/common": "^0.0.20",
42
42
  "@tscircuit/copper-pour-solver": "^0.0.51",
43
43
  "@tscircuit/create-fdm-enclosure": "0.0.4",
44
- "@tscircuit/fanout-solver": "0.0.45",
44
+ "@tscircuit/fanout-solver": "0.0.46",
45
45
  "@tscircuit/footprinter": "^0.0.426",
46
46
  "@tscircuit/image-utils": "^0.0.8",
47
47
  "@tscircuit/implicit-copper-pour-solver": "github:tscircuit/implicit-copper-pour-solver#47f930139fe969550e049aa7fb741bbcb1f08569",