@tscircuit/capacity-autorouter 0.0.28 → 0.0.29

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
@@ -74,6 +74,7 @@ interface CapacityMeshNode {
74
74
  _containsTarget?: boolean;
75
75
  _targetConnectionName?: string;
76
76
  _strawNode?: boolean;
77
+ _strawParentCapacityMeshNodeId?: CapacityMeshNodeId;
77
78
  _parent?: CapacityMeshNode;
78
79
  }
79
80
  interface CapacityMeshEdge {
@@ -252,7 +253,7 @@ declare class CapacityPathingSolver extends BaseSolver {
252
253
  getBacktrackedPath(candidate: Candidate): CapacityMeshNode[];
253
254
  getNeighboringNodes(node: CapacityMeshNode): CapacityMeshNode[];
254
255
  getCapacityPaths(): CapacityPath[];
255
- doesNodeHaveCapacityForTrace(node: CapacityMeshNode): boolean;
256
+ doesNodeHaveCapacityForTrace(node: CapacityMeshNode, prevNode: CapacityMeshNode): boolean;
256
257
  canTravelThroughObstacle(node: CapacityMeshNode, connectionName: string): boolean;
257
258
  getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode): number;
258
259
  reduceCapacityAlongPath(nextConnection: {
package/dist/index.js CHANGED
@@ -156,7 +156,8 @@ var CapacityMeshEdgeSolver = class extends BaseSolver {
156
156
  this.edges = [];
157
157
  for (let i = 0; i < this.nodes.length; i++) {
158
158
  for (let j = i + 1; j < this.nodes.length; j++) {
159
- if (!(this.nodes[i]._strawNode && this.nodes[j]._strawNode) && areNodesBordering(this.nodes[i], this.nodes[j]) && this.doNodesHaveSharedLayer(this.nodes[i], this.nodes[j])) {
159
+ const strawNodesWithSameParent = this.nodes[i]._strawNode && this.nodes[j]._strawNode && this.nodes[i]._strawParentCapacityMeshNodeId === this.nodes[j]._strawParentCapacityMeshNodeId;
160
+ if (!strawNodesWithSameParent && areNodesBordering(this.nodes[i], this.nodes[j]) && this.doNodesHaveSharedLayer(this.nodes[i], this.nodes[j])) {
160
161
  this.edges.push({
161
162
  capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),
162
163
  nodeIds: [
@@ -1113,6 +1114,29 @@ var mapLayerNameToZ = (layerName, layerCount) => {
1113
1114
  return parseInt(layerName.slice(5));
1114
1115
  };
1115
1116
 
1117
+ // lib/utils/getTunedTotalCapacity1.ts
1118
+ var getTunedTotalCapacity1 = (nodeOrWidth, maxCapacityFactor = 1) => {
1119
+ const VIA_DIAMETER = 0.6;
1120
+ const TRACE_WIDTH = 0.15;
1121
+ const obstacleMargin = 0.2;
1122
+ const width = "width" in nodeOrWidth ? nodeOrWidth.width : nodeOrWidth;
1123
+ const viaLengthAcross = width / (VIA_DIAMETER / 2 + obstacleMargin);
1124
+ return (viaLengthAcross / 2) ** 1.1 * maxCapacityFactor;
1125
+ };
1126
+ var calculateOptimalCapacityDepth = (initialWidth, targetMinCapacity = 0.5, maxDepth = 16) => {
1127
+ let depth = 0;
1128
+ let width = initialWidth;
1129
+ while (depth < maxDepth) {
1130
+ const capacity = getTunedTotalCapacity1({ width });
1131
+ if (capacity <= targetMinCapacity) {
1132
+ break;
1133
+ }
1134
+ width /= 2;
1135
+ depth++;
1136
+ }
1137
+ return Math.max(1, depth);
1138
+ };
1139
+
1116
1140
  // lib/solvers/CapacityMeshSolver/CapacityMeshNodeSolver1.ts
1117
1141
  var CapacityMeshNodeSolver = class extends BaseSolver {
1118
1142
  constructor(srj, opts = {}) {
@@ -1407,7 +1431,9 @@ var CapacityMeshNodeSolver = class extends BaseSolver {
1407
1431
  node.capacityMeshNodeId,
1408
1432
  `availableZ: ${node.availableZ.join(",")}`,
1409
1433
  `target? ${node._containsTarget ?? false}`,
1410
- `obs? ${node._containsObstacle ?? false}`
1434
+ `obs? ${node._containsObstacle ?? false}`,
1435
+ `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,
1436
+ `capacity: ${getTunedTotalCapacity1(node).toFixed(2)}`
1411
1437
  ].join("\n")
1412
1438
  });
1413
1439
  }
@@ -2058,7 +2084,7 @@ var SingleHighDensityRouteSolver = class extends BaseSolver {
2058
2084
  return false;
2059
2085
  }
2060
2086
  isNodeTooCloseToEdge(node, isVia) {
2061
- const margin = isVia ? this.viaDiameter / 2 : this.obstacleMargin;
2087
+ const margin = isVia ? this.viaDiameter / 2 + this.obstacleMargin / 2 : this.obstacleMargin / 2;
2062
2088
  const tooClose = node.x < this.bounds.minX + margin || node.x > this.bounds.maxX - margin || node.y < this.bounds.minY + margin || node.y > this.bounds.maxY - margin;
2063
2089
  if (tooClose && !isVia) {
2064
2090
  if (distance(node, this.B) < margin * 2 || distance(node, this.A) < margin * 2) {
@@ -3134,29 +3160,6 @@ var getConnectivityMapFromSimpleRouteJson = (srj) => {
3134
3160
  return connMap;
3135
3161
  };
3136
3162
 
3137
- // lib/utils/getTunedTotalCapacity1.ts
3138
- var getTunedTotalCapacity1 = (nodeOrWidth, maxCapacityFactor = 1) => {
3139
- const VIA_DIAMETER = 0.6;
3140
- const TRACE_WIDTH = 0.15;
3141
- const obstacleMargin = 0.2;
3142
- const width = "width" in nodeOrWidth ? nodeOrWidth.width : nodeOrWidth;
3143
- const viaLengthAcross = width / (VIA_DIAMETER / 2 + obstacleMargin);
3144
- return (viaLengthAcross / 2) ** 1.1 * maxCapacityFactor;
3145
- };
3146
- var calculateOptimalCapacityDepth = (initialWidth, targetMinCapacity = 0.5, maxDepth = 16) => {
3147
- let depth = 0;
3148
- let width = initialWidth;
3149
- while (depth < maxDepth) {
3150
- const capacity = getTunedTotalCapacity1({ width });
3151
- if (capacity <= targetMinCapacity) {
3152
- break;
3153
- }
3154
- width /= 2;
3155
- depth++;
3156
- }
3157
- return Math.max(1, depth);
3158
- };
3159
-
3160
3163
  // lib/solvers/NetToPointPairsSolver/buildMinimumSpanningTree.ts
3161
3164
  var KDNode = class {
3162
3165
  point;
@@ -5029,9 +5032,9 @@ var UnravelMultiSectionSolver = class extends BaseSolver {
5029
5032
  var createRectFromCapacityNode = (node, opts = {}) => {
5030
5033
  const lowestZ = Math.min(...node.availableZ);
5031
5034
  return {
5032
- center: !opts.rectMargin ? {
5033
- x: node.center.x + lowestZ * node.width * 0.05,
5034
- y: node.center.y - lowestZ * node.width * 0.05
5035
+ center: !opts.rectMargin || opts.zOffset ? {
5036
+ x: node.center.x + lowestZ * node.width * (opts.zOffset ?? 0.05),
5037
+ y: node.center.y - lowestZ * node.width * (opts.zOffset ?? 0.05)
5035
5038
  } : node.center,
5036
5039
  width: opts.rectMargin ? node.width - opts.rectMargin * 2 : Math.max(node.width - 0.5, node.width * 0.8),
5037
5040
  height: opts.rectMargin ? node.height - opts.rectMargin * 2 : Math.max(node.height - 0.5, node.height * 0.8),
@@ -5173,12 +5176,16 @@ var CapacityPathingSolver = class extends BaseSolver {
5173
5176
  }
5174
5177
  return capacityPaths;
5175
5178
  }
5176
- doesNodeHaveCapacityForTrace(node) {
5179
+ doesNodeHaveCapacityForTrace(node, prevNode) {
5177
5180
  const usedCapacity = this.usedNodeCapacityMap.get(node.capacityMeshNodeId) ?? 0;
5178
5181
  const totalCapacity = this.getTotalCapacity(node);
5179
5182
  if (node.availableZ.length === 1 && !node._containsTarget && usedCapacity > 0)
5180
5183
  return false;
5181
- return usedCapacity < totalCapacity;
5184
+ let additionalCapacityRequirement = 0;
5185
+ if (node.availableZ.length > 1 && prevNode.availableZ.length === 1) {
5186
+ additionalCapacityRequirement += 0.5;
5187
+ }
5188
+ return usedCapacity + additionalCapacityRequirement < totalCapacity;
5182
5189
  }
5183
5190
  canTravelThroughObstacle(node, connectionName) {
5184
5191
  const goalNodeIds = this.connectionNameToGoalNodeIds.get(connectionName);
@@ -5246,7 +5253,7 @@ var CapacityPathingSolver = class extends BaseSolver {
5246
5253
  if (this.visitedNodes?.has(neighborNode.capacityMeshNodeId)) {
5247
5254
  continue;
5248
5255
  }
5249
- if (!this.doesNodeHaveCapacityForTrace(neighborNode)) {
5256
+ if (!this.doesNodeHaveCapacityForTrace(neighborNode, currentCandidate.node)) {
5250
5257
  continue;
5251
5258
  }
5252
5259
  const connectionName = this.connectionsWithNodes[this.currentConnectionIndex].connection.name;
@@ -5285,27 +5292,42 @@ var CapacityPathingSolver = class extends BaseSolver {
5285
5292
  if (conn.path && conn.path.length > 0) {
5286
5293
  const pathPoints = conn.path.map(({ center: { x, y }, width }) => ({
5287
5294
  // slight offset to allow viewing overlapping paths
5288
- x: x + (i % 10 + i % 19) * (0.01 * width),
5289
- y: y + (i % 10 + i % 19) * (0.01 * width)
5295
+ x: x + (i % 10 + i % 19) * (5e-3 * width),
5296
+ y: y + (i % 10 + i % 19) * (5e-3 * width)
5290
5297
  }));
5291
5298
  graphics.lines.push({
5292
5299
  points: pathPoints,
5293
5300
  strokeColor: this.colorMap[conn.connection.name]
5294
5301
  });
5302
+ for (let u = 0; u < pathPoints.length; u++) {
5303
+ const point = pathPoints[u];
5304
+ graphics.points.push({
5305
+ x: point.x,
5306
+ y: point.y,
5307
+ label: [
5308
+ `conn: ${conn.connection.name}`,
5309
+ `node: ${conn.path[u].capacityMeshNodeId}`
5310
+ ].join("\n")
5311
+ });
5312
+ }
5295
5313
  }
5296
5314
  }
5297
5315
  }
5298
5316
  for (const node of this.nodes) {
5299
5317
  const nodeCosts = this.debug_lastNodeCostMap.get(node.capacityMeshNodeId);
5300
5318
  graphics.rects.push({
5301
- ...createRectFromCapacityNode(node),
5319
+ ...createRectFromCapacityNode(node, {
5320
+ rectMargin: 0.025,
5321
+ zOffset: 0.01
5322
+ }),
5302
5323
  label: [
5303
5324
  `${node.capacityMeshNodeId}`,
5304
5325
  `${this.usedNodeCapacityMap.get(node.capacityMeshNodeId)}/${this.getTotalCapacity(node).toFixed(2)}`,
5305
5326
  `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,
5306
5327
  `g: ${nodeCosts?.g !== void 0 ? nodeCosts.g.toFixed(2) : "?"}`,
5307
5328
  `h: ${nodeCosts?.h !== void 0 ? nodeCosts.h.toFixed(2) : "?"}`,
5308
- `f: ${nodeCosts?.f !== void 0 ? nodeCosts.f.toFixed(2) : "?"}`
5329
+ `f: ${nodeCosts?.f !== void 0 ? nodeCosts.f.toFixed(2) : "?"}`,
5330
+ `z: ${node.availableZ.join(", ")}`
5309
5331
  ].join("\n")
5310
5332
  });
5311
5333
  }
@@ -5315,7 +5337,8 @@ var CapacityPathingSolver = class extends BaseSolver {
5315
5337
  for (const point of conn.connection.pointsToConnect) {
5316
5338
  graphics.points.push({
5317
5339
  x: point.x,
5318
- y: point.y
5340
+ y: point.y,
5341
+ label: [`pointsToConnect ${conn.connection.name}`].join("\n")
5319
5342
  });
5320
5343
  }
5321
5344
  }
@@ -5371,18 +5394,6 @@ var CapacityPathingSolver5 = class extends CapacityPathingSolver {
5371
5394
  */
5372
5395
  getNodeCapacityPenalty(node) {
5373
5396
  return 0.05;
5374
- if (node.availableZ.length === 1) {
5375
- return 0;
5376
- }
5377
- const totalCapacity = this.getTotalCapacity(node);
5378
- const usedCapacity = this.usedNodeCapacityMap.get(node.capacityMeshNodeId) ?? 0;
5379
- const remainingCapacity = totalCapacity - usedCapacity;
5380
- const dist = this.activeCandidateStraightLineDistance;
5381
- if (remainingCapacity <= 0) {
5382
- const penalty = (-remainingCapacity + 1) / totalCapacity * dist * (this.NEGATIVE_CAPACITY_PENALTY_FACTOR / 4);
5383
- return penalty ** 2;
5384
- }
5385
- return 1 / remainingCapacity * dist * this.REDUCED_CAPACITY_PENALTY_FACTOR / 8;
5386
5397
  }
5387
5398
  /**
5388
5399
  * We're rewarding travel into big nodes.
@@ -5509,7 +5520,8 @@ var StrawSolver = class extends BaseSolver {
5509
5520
  layer: node.layer,
5510
5521
  availableZ: [...node.availableZ],
5511
5522
  _depth: node._depth,
5512
- _strawNode: true
5523
+ _strawNode: true,
5524
+ _strawParentCapacityMeshNodeId: node.capacityMeshNodeId
5513
5525
  });
5514
5526
  }
5515
5527
  } else {
@@ -5525,7 +5537,8 @@ var StrawSolver = class extends BaseSolver {
5525
5537
  layer: node.layer,
5526
5538
  availableZ: [...node.availableZ],
5527
5539
  _depth: node._depth,
5528
- _strawNode: true
5540
+ _strawNode: true,
5541
+ _strawParentCapacityMeshNodeId: node.capacityMeshNodeId
5529
5542
  });
5530
5543
  }
5531
5544
  }
@@ -5581,7 +5594,8 @@ ${node.width}x${node.height}`
5581
5594
  stroke: "rgba(0, 0, 0, 0.5)",
5582
5595
  label: `${node.capacityMeshNodeId}
5583
5596
  Layer: ${node.availableZ[0]}
5584
- ${node.width}x${node.height}`
5597
+ ${node.width}x${node.height}`,
5598
+ layer: `z${node.availableZ.join(",")}`
5585
5599
  });
5586
5600
  }
5587
5601
  for (const node of this.multiLayerNodes) {
@@ -5629,6 +5643,13 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
5629
5643
  }
5630
5644
  }
5631
5645
  nodeWithArea.sort((a, b) => a[1] - b[1]);
5646
+ for (const [nodeId, area] of nodeWithArea) {
5647
+ const node = this.nodeMap.get(nodeId);
5648
+ this.nodeMap.set(nodeId, {
5649
+ ...node,
5650
+ center: { ...node.center }
5651
+ });
5652
+ }
5632
5653
  this.currentBatchNodeIds = nodeWithArea.map((n) => n[0]);
5633
5654
  this.nextBatchNodeIds = [];
5634
5655
  this.batchHadModifications = false;
@@ -5887,7 +5908,7 @@ var SingleSimplifiedPathSolver = class extends BaseSolver {
5887
5908
  ],
5888
5909
  strokeColor: "rgba(255, 0, 0, 0.8)",
5889
5910
  strokeDash: this.inputRoute.route[i].z === 1 ? "5, 5" : void 0,
5890
- layer: this.inputRoute.route[i].z.toString()
5911
+ layer: `z${this.inputRoute.route[i].z.toString()}`
5891
5912
  });
5892
5913
  }
5893
5914
  for (let i = 0; i < this.newRoute.length; i++) {
@@ -5900,7 +5921,7 @@ var SingleSimplifiedPathSolver = class extends BaseSolver {
5900
5921
  strokeWidth: 0.15,
5901
5922
  strokeColor: "rgba(0, 255, 0, 0.8)",
5902
5923
  strokeDash: this.newRoute[i].z === 1 ? [0.4, 0.4] : void 0,
5903
- layer: this.newRoute[i].z.toString()
5924
+ layer: `z${this.newRoute[i].z.toString()}`
5904
5925
  });
5905
5926
  }
5906
5927
  graphics.points.push({
@@ -5908,7 +5929,7 @@ var SingleSimplifiedPathSolver = class extends BaseSolver {
5908
5929
  y: this.newRoute[i].y,
5909
5930
  color: "rgba(0, 255, 0, 0.8)",
5910
5931
  label: `z: ${this.newRoute[i].z}`,
5911
- layer: this.newRoute[i].z.toString()
5932
+ layer: `z${this.newRoute[i].z.toString()}`
5912
5933
  });
5913
5934
  }
5914
5935
  for (const via of this.newVias) {
@@ -5936,7 +5957,7 @@ var SingleSimplifiedPathSolver = class extends BaseSolver {
5936
5957
  strokeWidth: 0.15,
5937
5958
  strokeColor: route.route[i].z === 0 ? "rgba(255, 0, 255, 0.5)" : route.route[i].z === 1 ? "rgba(128, 0, 128, 0.5)" : "rgba(0, 0, 255, 0.5)",
5938
5959
  // bottom layer (blue)
5939
- layer: route.route[i].z.toString()
5960
+ layer: `z${route.route[i].z.toString()}`
5940
5961
  });
5941
5962
  }
5942
5963
  }
@@ -6481,7 +6502,7 @@ var MultiSimplifiedPathSolver = class extends BaseSolver {
6481
6502
  strokeColor: "rgba(255, 0, 0, 0.2)",
6482
6503
  strokeDash: [0.5, 0.5],
6483
6504
  step: 0,
6484
- layer: route.route[i].z.toString()
6505
+ layer: `z${route.route[i].z.toString()}`
6485
6506
  });
6486
6507
  }
6487
6508
  for (const point of route.vias) {
@@ -6587,17 +6608,18 @@ var CapacityMeshSolver = class extends BaseSolver {
6587
6608
  }
6588
6609
  }
6589
6610
  ),
6590
- // definePipelineStep("nodeSolver", CapacityMeshNodeSolver, (cms) => [
6591
- // cms.netToPointPairsSolver?.getNewSimpleRouteJson() || cms.srj,
6592
- // cms.opts,
6593
- // ]),
6594
6611
  definePipelineStep(
6595
6612
  "nodeSolver",
6596
6613
  CapacityMeshNodeSolver2_NodeUnderObstacle,
6597
6614
  (cms) => [
6598
6615
  cms.netToPointPairsSolver?.getNewSimpleRouteJson() || cms.srj,
6599
6616
  cms.opts
6600
- ]
6617
+ ],
6618
+ {
6619
+ onSolved: (cms) => {
6620
+ cms.capacityNodes = cms.nodeSolver?.finishedNodes;
6621
+ }
6622
+ }
6601
6623
  ),
6602
6624
  // definePipelineStep("nodeTargetMerger", CapacityNodeTargetMerger, (cms) => [
6603
6625
  // cms.nodeSolver?.finishedNodes || [],
@@ -6614,7 +6636,12 @@ var CapacityMeshSolver = class extends BaseSolver {
6614
6636
  definePipelineStep(
6615
6637
  "singleLayerNodeMerger",
6616
6638
  SingleLayerNodeMergerSolver,
6617
- (cms) => [cms.nodeSolver?.finishedNodes]
6639
+ (cms) => [cms.nodeSolver?.finishedNodes],
6640
+ {
6641
+ onSolved: (cms) => {
6642
+ cms.capacityNodes = cms.singleLayerNodeMerger?.newNodes;
6643
+ }
6644
+ }
6618
6645
  ),
6619
6646
  definePipelineStep(
6620
6647
  "strawSolver",