@tscircuit/schematic-trace-solver 0.0.145 → 0.0.147

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 (20) hide show
  1. package/dist/index.d.ts +9 -2
  2. package/dist/index.js +482 -86
  3. package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +38 -30
  4. package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +30 -8
  5. package/lib/solvers/InlineNetLabelSolver/pushAnchoredNetLabelsAwayFromInlineLabels.ts +530 -0
  6. package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +6 -21
  7. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +7 -23
  8. package/lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts +7 -14
  9. package/lib/types/InputProblem.ts +8 -0
  10. package/lib/utils/getNetLabelWidthForConnection.ts +63 -0
  11. package/package.json +1 -1
  12. package/tests/assets/inline-net-label-anchored-label-clearance.json +56 -0
  13. package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +80 -0
  14. package/tests/repros/repro-ti-power-output-section.input.ts +341 -0
  15. package/tests/repros/repro-ti-power-output-section.test.ts +13 -0
  16. package/tests/solvers/InlineNetLabelSolver/__snapshots__/fallback-net-label-width.snap.svg +69 -0
  17. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-anchored-label-clearance.snap.svg +54 -0
  18. package/tests/solvers/InlineNetLabelSolver/fallback-net-label-width.test.ts +152 -0
  19. package/tests/solvers/InlineNetLabelSolver/inline-net-label-anchored-label-clearance.test.ts +28 -0
  20. package/tests/solvers/InlineNetLabelSolver/push-anchored-net-labels-away.test.ts +227 -0
@@ -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(
@@ -18,6 +18,7 @@ import {
18
18
  getAxisAlignedSegments,
19
19
  } from "./getAxisAlignedSegments"
20
20
  import { alignPortOnlyInlineNetLabelStubs } from "./alignPortOnlyInlineNetLabelStubs"
21
+ import { pushAnchoredNetLabelsAwayFromInlineLabels } from "./pushAnchoredNetLabelsAwayFromInlineLabels"
21
22
 
22
23
  export const DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18
23
24
 
@@ -111,6 +112,11 @@ export class InlineNetLabelSolver extends BaseSolver {
111
112
 
112
113
  private tracesByPinPairKey: Map<string, SolvedTracePath[]>
113
114
  private hasAlignedPortOnlyStubs = false
115
+ private postProcessedOutput?: {
116
+ traces: SolvedTracePath[]
117
+ netLabelPlacements: NetLabelPlacement[]
118
+ inlineNetLabelPlacements: InlineNetLabelPlacement[]
119
+ }
114
120
 
115
121
  constructor(input: InlineNetLabelSolverInput) {
116
122
  super()
@@ -191,6 +197,11 @@ export class InlineNetLabelSolver extends BaseSolver {
191
197
  return
192
198
  }
193
199
 
200
+ if (!this.postProcessedOutput) {
201
+ this.postProcessedOutput = this.buildPostProcessedOutput()
202
+ return
203
+ }
204
+
194
205
  this.solved = true
195
206
  this.stats.inlineNetLabelCount = this.inlineNetLabelPlacements.length
196
207
  }
@@ -584,20 +595,31 @@ export class InlineNetLabelSolver extends BaseSolver {
584
595
  )
585
596
  }
586
597
 
587
- getOutput() {
598
+ private buildPostProcessedOutput() {
588
599
  const superseded = this.getSupersededNetLabelKeys()
600
+ const retainedNetLabelPlacements = this.inputNetLabelPlacements.filter(
601
+ (placement) => !superseded.has(placement.globalConnNetId),
602
+ )
603
+ const outputTraces = this.getOutputTraces(superseded)
604
+ const pushed = pushAnchoredNetLabelsAwayFromInlineLabels({
605
+ inputProblem: this.inputProblem,
606
+ traces: outputTraces,
607
+ netLabelPlacements: retainedNetLabelPlacements,
608
+ inlineNetLabelPlacements: this.inlineNetLabelPlacements,
609
+ })
610
+ this.stats.pushedAnchoredNetLabelCount = pushed.movedLabelCount
589
611
  return {
590
- // AvailableNetOrientationSolver may have routed an elbow from a port to
591
- // the anchored label that this inline placement supersedes. Keep the
592
- // actual net trace, but discard that now-orphaned label connector.
593
- traces: this.getOutputTraces(superseded),
594
- netLabelPlacements: this.inputNetLabelPlacements.filter(
595
- (placement) => !superseded.has(placement.globalConnNetId),
596
- ),
612
+ traces: pushed.traces,
613
+ netLabelPlacements: pushed.netLabelPlacements,
597
614
  inlineNetLabelPlacements: this.inlineNetLabelPlacements,
598
615
  }
599
616
  }
600
617
 
618
+ getOutput() {
619
+ if (this.postProcessedOutput) return this.postProcessedOutput
620
+ return this.buildPostProcessedOutput()
621
+ }
622
+
601
623
  override visualize(): GraphicsObject {
602
624
  // Mirrors the previous pipeline stage's visualization so that a problem
603
625
  // with no inline labels renders identically, then layers the inline labels