@tscircuit/schematic-trace-solver 0.0.146 → 0.0.148

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
@@ -88,6 +88,12 @@ interface InputDirectConnection {
88
88
  pinIds: [PinId, PinId];
89
89
  netId?: string;
90
90
  netLabelWidth?: number;
91
+ /**
92
+ * Width of the conventional anchored label to use only when an inline label
93
+ * cannot be placed. Unlike `netLabelWidth`, this does not affect whether or
94
+ * how the point-to-point connection is routed.
95
+ */
96
+ fallbackNetLabelWidth?: number;
91
97
  /**
92
98
  * When true, this point-to-point connection may be labeled with an "inline
93
99
  * net label": the net name is drawn parallel to (and offset from) the routed
@@ -116,6 +122,7 @@ interface InputNetConnection {
116
122
  netId: string;
117
123
  pinIds: Array<PinId>;
118
124
  netLabelWidth?: number;
125
+ fallbackNetLabelWidth?: number;
119
126
  netLabelHeight?: number;
120
127
  /**
121
128
  * When true, a named one- or two-pin net may use inline labels. A single-pin
@@ -221,7 +228,6 @@ declare class SchematicTraceSingleLineSolver2 extends BaseSolver {
221
228
  });
222
229
  getConstructorParams(): ConstructorParameters<typeof SchematicTraceSingleLineSolver2>[0];
223
230
  private getTextBoxPaddingForConnectionPair;
224
- private getNetLabelWidthForConnectionPair;
225
231
  private getNetLabelHeightForConnectionPair;
226
232
  private axisOfSegment;
227
233
  private pathLength;
@@ -855,7 +861,6 @@ declare class AvailableNetOrientationSolver extends BaseSolver {
855
861
  private getSearchDistanceLimit;
856
862
  private getLateralColumnMaxDistance;
857
863
  private createCandidate;
858
- private getNetLabelWidth;
859
864
  private getNetLabelHeight;
860
865
  private getCandidateStatus;
861
866
  private isAcceptableTraceAnchorChipCollision;
package/dist/index.js CHANGED
@@ -678,6 +678,50 @@ import "graphics-debug";
678
678
  // lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts
679
679
  import { calculateElbow as calculateElbow2 } from "calculate-elbow";
680
680
 
681
+ // lib/utils/getNetLabelWidthForConnection.ts
682
+ var getConfiguredWidth = (connections, includeFallbackNetLabelWidth) => {
683
+ const explicitWidth = connections.find(
684
+ (connection) => connection?.netLabelWidth !== void 0
685
+ )?.netLabelWidth;
686
+ if (explicitWidth !== void 0) return explicitWidth;
687
+ if (!includeFallbackNetLabelWidth) return void 0;
688
+ return connections.find(
689
+ (connection) => connection?.fallbackNetLabelWidth !== void 0
690
+ )?.fallbackNetLabelWidth;
691
+ };
692
+ var getNetLabelWidthForConnection = ({
693
+ inputProblem,
694
+ netId,
695
+ pinIds,
696
+ includeFallbackNetLabelWidth = true
697
+ }) => {
698
+ if (netId) {
699
+ const widthByNetId = getConfiguredWidth(
700
+ [
701
+ inputProblem.netConnections.find(
702
+ (connection) => connection.netId === netId
703
+ ),
704
+ inputProblem.directConnections.find(
705
+ (connection) => connection.netId === netId
706
+ )
707
+ ],
708
+ includeFallbackNetLabelWidth
709
+ );
710
+ if (widthByNetId !== void 0) return widthByNetId;
711
+ }
712
+ return getConfiguredWidth(
713
+ [
714
+ inputProblem.directConnections.find(
715
+ (connection) => connection.pinIds.some((pinId) => pinIds.includes(pinId))
716
+ ),
717
+ inputProblem.netConnections.find(
718
+ (connection) => connection.pinIds.some((pinId) => pinIds.includes(pinId))
719
+ )
720
+ ],
721
+ includeFallbackNetLabelWidth
722
+ );
723
+ };
724
+
681
725
  // lib/utils/textBoxBounds.ts
682
726
  function getTextBoxBounds(textBox, padding = {}) {
683
727
  return {
@@ -1281,7 +1325,12 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
1281
1325
  const netId = this.connectionPair?.userNetId;
1282
1326
  if (!netId) return {};
1283
1327
  const orientations = this.inputProblem.availableNetLabelOrientations[netId] ?? ["x+", "x-", "y+", "y-"];
1284
- const netLabelWidth = this.getNetLabelWidthForConnectionPair(netId);
1328
+ const netLabelWidth = getNetLabelWidthForConnection({
1329
+ inputProblem: this.inputProblem,
1330
+ netId,
1331
+ pinIds: this.pins.map((pin) => pin.pinId),
1332
+ includeFallbackNetLabelWidth: false
1333
+ });
1285
1334
  const netLabelHeight = this.getNetLabelHeightForConnectionPair(netId);
1286
1335
  const padding = {
1287
1336
  minX: 0,
@@ -1315,24 +1364,6 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
1315
1364
  }
1316
1365
  return padding;
1317
1366
  }
1318
- getNetLabelWidthForConnectionPair(netId) {
1319
- const ncWidth = this.inputProblem.netConnections.find(
1320
- (nc) => nc.netId === netId
1321
- )?.netLabelWidth;
1322
- if (ncWidth !== void 0) return ncWidth;
1323
- const dcWidthByNetId = this.inputProblem.directConnections.find(
1324
- (dc) => dc.netId === netId
1325
- )?.netLabelWidth;
1326
- if (dcWidthByNetId !== void 0) return dcWidthByNetId;
1327
- const pinIds = this.pins.map((p) => p.pinId);
1328
- const dcWidthByPinId = this.inputProblem.directConnections.find(
1329
- (dc) => dc.pinIds.some((pid) => pinIds.includes(pid))
1330
- )?.netLabelWidth;
1331
- if (dcWidthByPinId !== void 0) return dcWidthByPinId;
1332
- return this.inputProblem.netConnections.find(
1333
- (nc) => nc.pinIds.some((pid) => pinIds.includes(pid))
1334
- )?.netLabelWidth;
1335
- }
1336
1367
  getNetLabelHeightForConnectionPair(netId) {
1337
1368
  const ncHeight = this.inputProblem.netConnections.find(
1338
1369
  (nc) => nc.netId === netId
@@ -3217,27 +3248,15 @@ var NetLabelPlacementSolver = class extends BaseSolver {
3217
3248
  return groups;
3218
3249
  }
3219
3250
  getNetLabelWidthForGroup(group) {
3220
- if (group.netId) {
3221
- const ncWidth = this.inputProblem.netConnections.find(
3222
- (nc) => nc.netId === group.netId
3223
- )?.netLabelWidth;
3224
- if (ncWidth !== void 0) return ncWidth;
3225
- const dcWidthByNetId = this.inputProblem.directConnections.find(
3226
- (dc) => dc.netId === group.netId
3227
- )?.netLabelWidth;
3228
- if (dcWidthByNetId !== void 0) return dcWidthByNetId;
3229
- }
3230
3251
  const pinIds = group.overlappingTraces?.pins.map((p) => p.pinId) ?? [];
3231
3252
  if (group.portOnlyPinId) {
3232
3253
  pinIds.push(group.portOnlyPinId);
3233
3254
  }
3234
- const dcWidthByPinId = this.inputProblem.directConnections.find(
3235
- (dc) => dc.pinIds.some((pid) => pinIds.includes(pid))
3236
- )?.netLabelWidth;
3237
- if (dcWidthByPinId !== void 0) return dcWidthByPinId;
3238
- return this.inputProblem.netConnections.find(
3239
- (nc) => nc.pinIds.some((pid) => pinIds.includes(pid))
3240
- )?.netLabelWidth;
3255
+ return getNetLabelWidthForConnection({
3256
+ inputProblem: this.inputProblem,
3257
+ netId: group.netId,
3258
+ pinIds
3259
+ });
3241
3260
  }
3242
3261
  getNetLabelHeightForGroup(group) {
3243
3262
  if (group.netId) {
@@ -6333,6 +6352,51 @@ var generateLShapeRerouteCandidates = ({
6333
6352
  }
6334
6353
  return [[i1_padded, c2, i2_padded]];
6335
6354
  };
6355
+ var generatePerimeterCornerTraceDetours = ({
6356
+ trace,
6357
+ chipBounds,
6358
+ clearance
6359
+ }) => {
6360
+ if (trace.tracePath.length < 4 || chipBounds.length === 0) return [];
6361
+ const start = trace.tracePath[0];
6362
+ const firstEscape = trace.tracePath[1];
6363
+ const lastEscape = trace.tracePath.at(-2);
6364
+ const end = trace.tracePath.at(-1);
6365
+ const minX = Math.min(...chipBounds.map((bounds) => bounds.minX)) - clearance;
6366
+ const maxX = Math.max(...chipBounds.map((bounds) => bounds.maxX)) + clearance;
6367
+ const minY = Math.min(...chipBounds.map((bounds) => bounds.minY)) - clearance;
6368
+ const maxY = Math.max(...chipBounds.map((bounds) => bounds.maxY)) + clearance;
6369
+ const candidates = [];
6370
+ for (const channelX of [minX, maxX]) {
6371
+ for (const channelY of [minY, maxY]) {
6372
+ candidates.push({
6373
+ traceId: trace.mspPairId,
6374
+ path: simplifyPath([
6375
+ start,
6376
+ firstEscape,
6377
+ { x: firstEscape.x, y: channelY },
6378
+ { x: channelX, y: channelY },
6379
+ { x: channelX, y: lastEscape.y },
6380
+ lastEscape,
6381
+ end
6382
+ ])
6383
+ });
6384
+ candidates.push({
6385
+ traceId: trace.mspPairId,
6386
+ path: simplifyPath([
6387
+ start,
6388
+ firstEscape,
6389
+ { x: channelX, y: firstEscape.y },
6390
+ { x: channelX, y: channelY },
6391
+ { x: lastEscape.x, y: channelY },
6392
+ lastEscape,
6393
+ end
6394
+ ])
6395
+ });
6396
+ }
6397
+ }
6398
+ return candidates;
6399
+ };
6336
6400
  var generatePerpendicularTraceDetours = ({
6337
6401
  trace,
6338
6402
  segmentIndex,
@@ -6644,7 +6708,8 @@ var UntangleTraceSubsolver = class extends BaseSolver {
6644
6708
  const otherTrace = traces[secondIndex];
6645
6709
  if (trace.globalConnNetId === otherTrace.globalConnNetId) continue;
6646
6710
  const isInitialBundleCrossing = this._isTraceBundle(trace, otherTrace);
6647
- if (!isInitialBundleCrossing && !this.reroutedTraceIds.has(trace.mspPairId) && !this.reroutedTraceIds.has(otherTrace.mspPairId)) {
6711
+ const isEligibleInitialCrossing = this.input.eligibleTraceIds?.has(trace.mspPairId) === true || this.input.eligibleTraceIds?.has(otherTrace.mspPairId) === true;
6712
+ if (!isInitialBundleCrossing && !isEligibleInitialCrossing && !this.reroutedTraceIds.has(trace.mspPairId) && !this.reroutedTraceIds.has(otherTrace.mspPairId)) {
6648
6713
  continue;
6649
6714
  }
6650
6715
  const crossings = findPerpendicularPathCrossings(
@@ -6687,6 +6752,16 @@ var UntangleTraceSubsolver = class extends BaseSolver {
6687
6752
  obstacleEnd: crossing.trace.tracePath[crossing.segmentIndex + 1],
6688
6753
  chipBounds,
6689
6754
  clearance: this.input.paddingBuffer
6755
+ }),
6756
+ ...generatePerimeterCornerTraceDetours({
6757
+ trace: crossing.trace,
6758
+ chipBounds,
6759
+ clearance: this.input.paddingBuffer
6760
+ }),
6761
+ ...generatePerimeterCornerTraceDetours({
6762
+ trace: crossing.otherTrace,
6763
+ chipBounds,
6764
+ clearance: this.input.paddingBuffer
6690
6765
  })
6691
6766
  ];
6692
6767
  const chipObstacles = getObstacleRects(this.input.inputProblem).filter(
@@ -8527,13 +8602,21 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8527
8602
  const bY = this.outputNetLabelPlacements[b].anchorPoint.y;
8528
8603
  return requiredOrientation === "y+" ? bY - aY : aY - bY;
8529
8604
  });
8530
- const blockedLabelWidth = this.getNetLabelWidth(blockedLabel);
8605
+ const blockedLabelWidth = getNetLabelWidthForConnection({
8606
+ inputProblem: this.inputProblem,
8607
+ netId: blockedLabel.netId,
8608
+ pinIds: blockedLabel.pinIds
8609
+ });
8531
8610
  let columnLabelIndex;
8532
8611
  if (blockedLabelWidth !== void 0) {
8533
8612
  columnLabelIndex = labelsToOrder.find((index) => {
8534
8613
  if (index === blockedStandaloneLabelIndex) return false;
8535
8614
  const label = this.outputNetLabelPlacements[index];
8536
- return this.getNetLabelWidth(label) === blockedLabelWidth;
8615
+ return getNetLabelWidthForConnection({
8616
+ inputProblem: this.inputProblem,
8617
+ netId: label.netId,
8618
+ pinIds: label.pinIds
8619
+ }) === blockedLabelWidth;
8537
8620
  });
8538
8621
  }
8539
8622
  if (columnLabelIndex !== void 0) {
@@ -8754,7 +8837,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8754
8837
  if (!chip) return null;
8755
8838
  const { width, height } = getDimsForOrientation({
8756
8839
  orientation,
8757
- netLabelWidth: this.getNetLabelWidth(label),
8840
+ netLabelWidth: getNetLabelWidthForConnection({
8841
+ inputProblem: this.inputProblem,
8842
+ netId: label.netId,
8843
+ pinIds: label.pinIds
8844
+ }),
8758
8845
  netLabelHeight: this.getNetLabelHeight(label)
8759
8846
  });
8760
8847
  const nextPinToRight = this.outputNetLabelPlacements.map((otherLabel, index) => ({
@@ -9188,7 +9275,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9188
9275
  labelIntersectsDifferentNetTrace(label) {
9189
9276
  const { width, height } = getDimsForOrientation({
9190
9277
  orientation: label.orientation,
9191
- netLabelWidth: this.getNetLabelWidth(label),
9278
+ netLabelWidth: getNetLabelWidthForConnection({
9279
+ inputProblem: this.inputProblem,
9280
+ netId: label.netId,
9281
+ pinIds: label.pinIds
9282
+ }),
9192
9283
  netLabelHeight: this.getNetLabelHeight(label)
9193
9284
  });
9194
9285
  const center = getCenterFromAnchor(
@@ -9206,7 +9297,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9206
9297
  const anchorPoint = this.getWickOffsetAnchor(label.anchorPoint, orientation);
9207
9298
  const { width, height } = getDimsForOrientation({
9208
9299
  orientation,
9209
- netLabelWidth: this.getNetLabelWidth(label),
9300
+ netLabelWidth: getNetLabelWidthForConnection({
9301
+ inputProblem: this.inputProblem,
9302
+ netId: label.netId,
9303
+ pinIds: label.pinIds
9304
+ }),
9210
9305
  netLabelHeight: this.getNetLabelHeight(label)
9211
9306
  });
9212
9307
  const searchStartAnchor = this.getSideOffsetAnchor({
@@ -9261,7 +9356,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9261
9356
  getSearchDistanceLimit(label, orientation) {
9262
9357
  const { width, height } = getDimsForOrientation({
9263
9358
  orientation,
9264
- netLabelWidth: this.getNetLabelWidth(label),
9359
+ netLabelWidth: getNetLabelWidthForConnection({
9360
+ inputProblem: this.inputProblem,
9361
+ netId: label.netId,
9362
+ pinIds: label.pinIds
9363
+ }),
9265
9364
  netLabelHeight: this.getNetLabelHeight(label)
9266
9365
  });
9267
9366
  const labelLength = orientation === "y+" || orientation === "y-" ? height : width;
@@ -9312,7 +9411,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9312
9411
  createCandidate(label, anchorPoint, orientation, connectorSource) {
9313
9412
  const { width, height } = getDimsForOrientation({
9314
9413
  orientation,
9315
- netLabelWidth: this.getNetLabelWidth(label),
9414
+ netLabelWidth: getNetLabelWidthForConnection({
9415
+ inputProblem: this.inputProblem,
9416
+ netId: label.netId,
9417
+ pinIds: label.pinIds
9418
+ }),
9316
9419
  netLabelHeight: this.getNetLabelHeight(label)
9317
9420
  });
9318
9421
  return {
@@ -9324,25 +9427,6 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9324
9427
  center: getCenterFromAnchor(anchorPoint, orientation, width, height)
9325
9428
  };
9326
9429
  }
9327
- getNetLabelWidth(label) {
9328
- if (label.netId) {
9329
- const ncWidth = this.inputProblem.netConnections.find(
9330
- (connection) => connection.netId === label.netId
9331
- )?.netLabelWidth;
9332
- if (ncWidth !== void 0) return ncWidth;
9333
- const dcWidthByNetId = this.inputProblem.directConnections.find(
9334
- (dc) => dc.netId === label.netId
9335
- )?.netLabelWidth;
9336
- if (dcWidthByNetId !== void 0) return dcWidthByNetId;
9337
- }
9338
- const dcWidthByPinId = this.inputProblem.directConnections.find(
9339
- (dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid))
9340
- )?.netLabelWidth;
9341
- if (dcWidthByPinId !== void 0) return dcWidthByPinId;
9342
- return this.inputProblem.netConnections.find(
9343
- (nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
9344
- )?.netLabelWidth;
9345
- }
9346
9430
  getNetLabelHeight(label) {
9347
9431
  if (label.netId) {
9348
9432
  const ncHeight = this.inputProblem.netConnections.find(
@@ -10541,18 +10625,12 @@ var getChipBounds = (inputProblem) => {
10541
10625
  };
10542
10626
  };
10543
10627
  var getNetLabelWidth = (inputProblem, label) => {
10544
- const ncWidthByNetId = inputProblem.netConnections.find(
10545
- (connection) => connection.netId === label.netId
10546
- )?.netLabelWidth;
10547
- if (ncWidthByNetId !== void 0) return ncWidthByNetId;
10548
- const dcWidth = inputProblem.directConnections.find(
10549
- (dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid))
10550
- )?.netLabelWidth;
10551
- if (dcWidth !== void 0) return dcWidth;
10552
- const ncWidthByPinId = inputProblem.netConnections.find(
10553
- (nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
10554
- )?.netLabelWidth;
10555
- if (ncWidthByPinId !== void 0) return ncWidthByPinId;
10628
+ const configuredWidth = getNetLabelWidthForConnection({
10629
+ inputProblem,
10630
+ netId: label.netId,
10631
+ pinIds: label.pinIds
10632
+ });
10633
+ if (configuredWidth !== void 0) return configuredWidth;
10556
10634
  if (label.orientation === "y+" || label.orientation === "y-") {
10557
10635
  return label.height;
10558
10636
  }
@@ -13781,6 +13859,42 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
13781
13859
  definePipelineStep("traceCleanupSolver", TraceCleanupSolver, (instance) => {
13782
13860
  const prevSolverOutput = instance.traceElbowTransitionSimplificationSolver.getOutput();
13783
13861
  const traces = prevSolverOutput.traces;
13862
+ const overlapShiftSolver = instance.traceOverlapShiftSolver;
13863
+ const inlineLabelNetIds = new Set(
13864
+ [
13865
+ ...instance.inputProblem.directConnections,
13866
+ ...instance.inputProblem.netConnections
13867
+ ].filter((connection) => connection.allowInlineNetLabel).map((connection) => connection.netId)
13868
+ );
13869
+ const traceIdsInNewCrossingsAfterOverlapShift = /* @__PURE__ */ new Set();
13870
+ for (let traceIndex = 0; traceIndex < overlapShiftSolver.inputTracePaths.length; traceIndex++) {
13871
+ const inputTrace = overlapShiftSolver.inputTracePaths[traceIndex];
13872
+ const shiftedTrace = overlapShiftSolver.correctedTraceMap[inputTrace.mspPairId];
13873
+ for (let otherTraceIndex = traceIndex + 1; otherTraceIndex < overlapShiftSolver.inputTracePaths.length; otherTraceIndex++) {
13874
+ const otherInputTrace = overlapShiftSolver.inputTracePaths[otherTraceIndex];
13875
+ if (inputTrace.globalConnNetId === otherInputTrace.globalConnNetId) {
13876
+ continue;
13877
+ }
13878
+ if (!inlineLabelNetIds.has(inputTrace.userNetId ?? "") && !inlineLabelNetIds.has(otherInputTrace.userNetId ?? "")) {
13879
+ continue;
13880
+ }
13881
+ const otherShiftedTrace = overlapShiftSolver.correctedTraceMap[otherInputTrace.mspPairId];
13882
+ const crossingCountBeforeShift = findPerpendicularPathCrossings(
13883
+ inputTrace.tracePath,
13884
+ otherInputTrace.tracePath
13885
+ ).length;
13886
+ const crossingCountAfterShift = findPerpendicularPathCrossings(
13887
+ shiftedTrace.tracePath,
13888
+ otherShiftedTrace.tracePath
13889
+ ).length;
13890
+ if (crossingCountAfterShift > crossingCountBeforeShift) {
13891
+ traceIdsInNewCrossingsAfterOverlapShift.add(inputTrace.mspPairId);
13892
+ traceIdsInNewCrossingsAfterOverlapShift.add(
13893
+ otherInputTrace.mspPairId
13894
+ );
13895
+ }
13896
+ }
13897
+ }
13784
13898
  const labelMergingOutput = instance.traceLabelOverlapAvoidanceSolver.labelMergingSolver.getOutput();
13785
13899
  return [
13786
13900
  {
@@ -13788,7 +13902,8 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
13788
13902
  allTraces: traces,
13789
13903
  allLabelPlacements: labelMergingOutput.netLabelPlacements,
13790
13904
  mergedLabelNetIdMap: labelMergingOutput.mergedLabelNetIdMap,
13791
- paddingBuffer: 0.1
13905
+ paddingBuffer: 0.1,
13906
+ eligibleTraceIds: traceIdsInNewCrossingsAfterOverlapShift
13792
13907
  }
13793
13908
  ];
13794
13909
  }),
@@ -16,6 +16,7 @@ import type {
16
16
  InputProblem,
17
17
  } from "lib/types/InputProblem"
18
18
  import { dir, type FacingDirection } from "lib/utils/dir"
19
+ import { getNetLabelWidthForConnection } from "lib/utils/getNetLabelWidthForConnection"
19
20
  import { rectIntersectsAnyTextBox } from "lib/utils/textBoxBounds"
20
21
  import {
21
22
  EPS,
@@ -180,13 +181,23 @@ export class AvailableNetOrientationSolver extends BaseSolver {
180
181
  const bY = this.outputNetLabelPlacements[b]!.anchorPoint.y
181
182
  return requiredOrientation === "y+" ? bY - aY : aY - bY
182
183
  })
183
- const blockedLabelWidth = this.getNetLabelWidth(blockedLabel)
184
+ const blockedLabelWidth = getNetLabelWidthForConnection({
185
+ inputProblem: this.inputProblem,
186
+ netId: blockedLabel.netId,
187
+ pinIds: blockedLabel.pinIds,
188
+ })
184
189
  let columnLabelIndex: number | undefined
185
190
  if (blockedLabelWidth !== undefined) {
186
191
  columnLabelIndex = labelsToOrder.find((index) => {
187
192
  if (index === blockedStandaloneLabelIndex) return false
188
193
  const label = this.outputNetLabelPlacements[index]!
189
- return this.getNetLabelWidth(label) === blockedLabelWidth
194
+ return (
195
+ getNetLabelWidthForConnection({
196
+ inputProblem: this.inputProblem,
197
+ netId: label.netId,
198
+ pinIds: label.pinIds,
199
+ }) === blockedLabelWidth
200
+ )
190
201
  })
191
202
  }
192
203
  if (columnLabelIndex !== undefined) {
@@ -481,7 +492,11 @@ export class AvailableNetOrientationSolver extends BaseSolver {
481
492
 
482
493
  const { width, height } = getDimsForOrientation({
483
494
  orientation,
484
- netLabelWidth: this.getNetLabelWidth(label),
495
+ netLabelWidth: getNetLabelWidthForConnection({
496
+ inputProblem: this.inputProblem,
497
+ netId: label.netId,
498
+ pinIds: label.pinIds,
499
+ }),
485
500
  netLabelHeight: this.getNetLabelHeight(label),
486
501
  })
487
502
 
@@ -1094,7 +1109,11 @@ export class AvailableNetOrientationSolver extends BaseSolver {
1094
1109
  private labelIntersectsDifferentNetTrace(label: NetLabelPlacement) {
1095
1110
  const { width, height } = getDimsForOrientation({
1096
1111
  orientation: label.orientation,
1097
- netLabelWidth: this.getNetLabelWidth(label),
1112
+ netLabelWidth: getNetLabelWidthForConnection({
1113
+ inputProblem: this.inputProblem,
1114
+ netId: label.netId,
1115
+ pinIds: label.pinIds,
1116
+ }),
1098
1117
  netLabelHeight: this.getNetLabelHeight(label),
1099
1118
  })
1100
1119
  const center = getCenterFromAnchor(
@@ -1118,7 +1137,11 @@ export class AvailableNetOrientationSolver extends BaseSolver {
1118
1137
  const anchorPoint = this.getWickOffsetAnchor(label.anchorPoint, orientation)
1119
1138
  const { width, height } = getDimsForOrientation({
1120
1139
  orientation,
1121
- netLabelWidth: this.getNetLabelWidth(label),
1140
+ netLabelWidth: getNetLabelWidthForConnection({
1141
+ inputProblem: this.inputProblem,
1142
+ netId: label.netId,
1143
+ pinIds: label.pinIds,
1144
+ }),
1122
1145
  netLabelHeight: this.getNetLabelHeight(label),
1123
1146
  })
1124
1147
 
@@ -1197,7 +1220,11 @@ export class AvailableNetOrientationSolver extends BaseSolver {
1197
1220
  ) {
1198
1221
  const { width, height } = getDimsForOrientation({
1199
1222
  orientation,
1200
- netLabelWidth: this.getNetLabelWidth(label),
1223
+ netLabelWidth: getNetLabelWidthForConnection({
1224
+ inputProblem: this.inputProblem,
1225
+ netId: label.netId,
1226
+ pinIds: label.pinIds,
1227
+ }),
1201
1228
  netLabelHeight: this.getNetLabelHeight(label),
1202
1229
  })
1203
1230
  const labelLength =
@@ -1278,7 +1305,11 @@ export class AvailableNetOrientationSolver extends BaseSolver {
1278
1305
  ): CandidateLabel {
1279
1306
  const { width, height } = getDimsForOrientation({
1280
1307
  orientation,
1281
- netLabelWidth: this.getNetLabelWidth(label),
1308
+ netLabelWidth: getNetLabelWidthForConnection({
1309
+ inputProblem: this.inputProblem,
1310
+ netId: label.netId,
1311
+ pinIds: label.pinIds,
1312
+ }),
1282
1313
  netLabelHeight: this.getNetLabelHeight(label),
1283
1314
  })
1284
1315
  return {
@@ -1291,29 +1322,6 @@ export class AvailableNetOrientationSolver extends BaseSolver {
1291
1322
  }
1292
1323
  }
1293
1324
 
1294
- private getNetLabelWidth(label: NetLabelPlacement) {
1295
- if (label.netId) {
1296
- const ncWidth = this.inputProblem.netConnections.find(
1297
- (connection) => connection.netId === label.netId,
1298
- )?.netLabelWidth
1299
- if (ncWidth !== undefined) return ncWidth
1300
-
1301
- const dcWidthByNetId = this.inputProblem.directConnections.find(
1302
- (dc) => dc.netId === label.netId,
1303
- )?.netLabelWidth
1304
- if (dcWidthByNetId !== undefined) return dcWidthByNetId
1305
- }
1306
-
1307
- const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
1308
- dc.pinIds.some((pid) => label.pinIds.includes(pid)),
1309
- )?.netLabelWidth
1310
- if (dcWidthByPinId !== undefined) return dcWidthByPinId
1311
-
1312
- return this.inputProblem.netConnections.find((nc) =>
1313
- nc.pinIds.some((pid) => label.pinIds.includes(pid)),
1314
- )?.netLabelWidth
1315
- }
1316
-
1317
1325
  private getNetLabelHeight(label: NetLabelPlacement) {
1318
1326
  if (label.netId) {
1319
1327
  const ncHeight = this.inputProblem.netConnections.find(
@@ -9,6 +9,7 @@ import type { GraphicsObject } from "graphics-debug"
9
9
  import { visualizeInputProblem } from "../SchematicTracePipelineSolver/visualizeInputProblem"
10
10
  import { getColorFromString } from "lib/utils/getColorFromString"
11
11
  import { getConnectivityMapsFromInputProblem } from "../MspConnectionPairSolver/getConnectivityMapFromInputProblem"
12
+ import { getNetLabelWidthForConnection } from "lib/utils/getNetLabelWidthForConnection"
12
13
 
13
14
  /**
14
15
  * A group of traces that have at least one overlapping segment and
@@ -261,31 +262,15 @@ export class NetLabelPlacementSolver extends BaseSolver {
261
262
  private getNetLabelWidthForGroup(
262
263
  group: OverlappingSameNetTraceGroup,
263
264
  ): number | undefined {
264
- if (group.netId) {
265
- const ncWidth = this.inputProblem.netConnections.find(
266
- (nc) => nc.netId === group.netId,
267
- )?.netLabelWidth
268
- if (ncWidth !== undefined) return ncWidth
269
-
270
- const dcWidthByNetId = this.inputProblem.directConnections.find(
271
- (dc) => dc.netId === group.netId,
272
- )?.netLabelWidth
273
- if (dcWidthByNetId !== undefined) return dcWidthByNetId
274
- }
275
-
276
265
  const pinIds = group.overlappingTraces?.pins.map((p) => p.pinId) ?? []
277
266
  if (group.portOnlyPinId) {
278
267
  pinIds.push(group.portOnlyPinId)
279
268
  }
280
-
281
- const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
282
- dc.pinIds.some((pid) => pinIds.includes(pid)),
283
- )?.netLabelWidth
284
- if (dcWidthByPinId !== undefined) return dcWidthByPinId
285
-
286
- return this.inputProblem.netConnections.find((nc) =>
287
- nc.pinIds.some((pid) => pinIds.includes(pid)),
288
- )?.netLabelWidth
269
+ return getNetLabelWidthForConnection({
270
+ inputProblem: this.inputProblem,
271
+ netId: group.netId,
272
+ pinIds,
273
+ })
289
274
  }
290
275
 
291
276
  private getNetLabelHeightForGroup(
@@ -7,6 +7,7 @@ import { getDimsForOrientation } from "lib/solvers/NetLabelPlacementSolver/Singl
7
7
  import { visualizeInputProblem } from "lib/solvers/SchematicTracePipelineSolver/visualizeInputProblem"
8
8
  import type { InputChip, InputProblem } from "lib/types/InputProblem"
9
9
  import type { FacingDirection } from "lib/utils/dir"
10
+ import { getNetLabelWidthForConnection } from "lib/utils/getNetLabelWidthForConnection"
10
11
  import { getTextBoxBounds, type RectPadding } from "lib/utils/textBoxBounds"
11
12
  import { getPinDirection } from "../SchematicTraceSingleLineSolver/getPinDirection"
12
13
  import { calculateDirectShortPath } from "./calculateDirectShortPath"
@@ -201,7 +202,12 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
201
202
  const orientations =
202
203
  this.inputProblem.availableNetLabelOrientations[netId] ??
203
204
  (["x+", "x-", "y+", "y-"] as FacingDirection[])
204
- const netLabelWidth = this.getNetLabelWidthForConnectionPair(netId)
205
+ const netLabelWidth = getNetLabelWidthForConnection({
206
+ inputProblem: this.inputProblem,
207
+ netId,
208
+ pinIds: this.pins.map((pin) => pin.pinId),
209
+ includeFallbackNetLabelWidth: false,
210
+ })
205
211
  const netLabelHeight = this.getNetLabelHeightForConnectionPair(netId)
206
212
  const padding: Required<RectPadding> = {
207
213
  minX: 0,
@@ -239,28 +245,6 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
239
245
  return padding
240
246
  }
241
247
 
242
- private getNetLabelWidthForConnectionPair(netId: string) {
243
- const ncWidth = this.inputProblem.netConnections.find(
244
- (nc) => nc.netId === netId,
245
- )?.netLabelWidth
246
- if (ncWidth !== undefined) return ncWidth
247
-
248
- const dcWidthByNetId = this.inputProblem.directConnections.find(
249
- (dc) => dc.netId === netId,
250
- )?.netLabelWidth
251
- if (dcWidthByNetId !== undefined) return dcWidthByNetId
252
-
253
- const pinIds = this.pins.map((p) => p.pinId)
254
- const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
255
- dc.pinIds.some((pid) => pinIds.includes(pid)),
256
- )?.netLabelWidth
257
- if (dcWidthByPinId !== undefined) return dcWidthByPinId
258
-
259
- return this.inputProblem.netConnections.find((nc) =>
260
- nc.pinIds.some((pid) => pinIds.includes(pid)),
261
- )?.netLabelWidth
262
- }
263
-
264
248
  private getNetLabelHeightForConnectionPair(netId: string) {
265
249
  const ncHeight = this.inputProblem.netConnections.find(
266
250
  (nc) => nc.netId === netId,