@tscircuit/schematic-trace-solver 0.0.125 → 0.0.127

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 (28) hide show
  1. package/README.md +28 -0
  2. package/dist/index.d.ts +159 -2
  3. package/dist/index.js +739 -36
  4. package/lib/index.ts +2 -0
  5. package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +424 -0
  6. package/lib/solvers/InlineNetLabelSolver/getAxisAlignedSegments.ts +73 -0
  7. package/lib/solvers/NetLabelTraceCollisionSolver/NetLabelTraceCollisionSolver.ts +15 -0
  8. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +86 -11
  9. package/lib/solvers/TraceElbowTransitionSimplificationSolver/TraceElbowTransitionSimplificationSolver.ts +216 -0
  10. package/lib/solvers/TraceElbowTransitionSimplificationSolver/generateElbowTransitionSimplificationCandidates.ts +186 -0
  11. package/lib/solvers/TraceElbowTransitionSimplificationSolver/types.ts +10 -0
  12. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/TraceLabelOverlapAvoidanceSolver.ts +3 -0
  13. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/OverlapAvoidanceStepSolver/OverlapAvoidanceStepSolver.ts +16 -0
  14. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/SingleOverlapSolver/SingleOverlapSolver.ts +56 -13
  15. package/lib/types/InputProblem.ts +24 -0
  16. package/package.json +1 -1
  17. package/site/bug-reports/bug-report-20260806T093501Z.page.tsx +4 -0
  18. package/site/examples/inline-net-label01.page.tsx +6 -0
  19. package/tests/assets/inline-net-label01.json +47 -0
  20. package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +3 -3
  21. package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +6 -6
  22. package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +135 -0
  23. package/tests/bug-reports/bug-report-20260806T093501Z/bug-report-20260806T093501Z.json +505 -0
  24. package/tests/bug-reports/bug-report-20260806T093501Z/bug-report-20260806T093501Z.test.ts +66 -0
  25. package/tests/examples/__snapshots__/example33.snap.svg +1 -1
  26. package/tests/functions/getAxisAlignedSegments.test.ts +56 -0
  27. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label01.snap.svg +54 -0
  28. package/tests/solvers/InlineNetLabelSolver/inline-net-label01.test.ts +44 -0
package/dist/index.js CHANGED
@@ -4000,6 +4000,16 @@ var doesPathOverlapTraceStrokes = (path, traces) => {
4000
4000
 
4001
4001
  // lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/SingleOverlapSolver/SingleOverlapSolver.ts
4002
4002
  var MAX_TRIES = 5;
4003
+ var PATH_LENGTH_EPSILON = 1e-9;
4004
+ var getPathLength = (points) => {
4005
+ let length = 0;
4006
+ for (let pointIndex = 0; pointIndex < points.length - 1; pointIndex++) {
4007
+ const point = points[pointIndex];
4008
+ const nextPoint = points[pointIndex + 1];
4009
+ length += Math.abs(nextPoint.x - point.x) + Math.abs(nextPoint.y - point.y);
4010
+ }
4011
+ return length;
4012
+ };
4003
4013
  var SingleOverlapSolver = class extends BaseSolver {
4004
4014
  queuedCandidatePaths;
4005
4015
  solvedTracePath = null;
@@ -4008,32 +4018,47 @@ var SingleOverlapSolver = class extends BaseSolver {
4008
4018
  obstacles;
4009
4019
  label;
4010
4020
  tracesToAvoidOverlapping;
4021
+ netLabelPlacements;
4022
+ detourCount;
4011
4023
  _tried = 0;
4012
4024
  constructor(solverInput) {
4013
4025
  super();
4014
4026
  this.initialTrace = solverInput.trace;
4015
4027
  this.problem = solverInput.problem;
4016
4028
  this.label = solverInput.label;
4029
+ this.detourCount = solverInput.detourCount;
4017
4030
  this.tracesToAvoidOverlapping = (solverInput.tracesToAvoidOverlapping ?? []).filter((t) => t.globalConnNetId !== solverInput.trace.globalConnNetId);
4031
+ this.netLabelPlacements = solverInput.netLabelPlacements ?? [
4032
+ solverInput.label
4033
+ ];
4034
+ this.obstacles = getObstacleRects(this.problem);
4018
4035
  const effectivePadding = solverInput.paddingBuffer + solverInput.detourCount * solverInput.paddingBuffer;
4019
4036
  const candidates = generateRerouteCandidates({
4020
4037
  ...solverInput,
4021
4038
  paddingBuffer: effectivePadding
4022
4039
  // Use the calculated, larger padding
4023
4040
  });
4024
- const getPathLength3 = (pts) => {
4025
- let len = 0;
4026
- for (let i = 0; i < pts.length - 1; i++) {
4027
- const dx = pts[i + 1].x - pts[i].x;
4028
- const dy = pts[i + 1].y - pts[i].y;
4029
- len += Math.sqrt(dx * dx + dy * dy);
4030
- }
4031
- return len;
4032
- };
4033
- this.queuedCandidatePaths = candidates.sort(
4034
- (a, b) => getPathLength3(a) - getPathLength3(b)
4035
- );
4036
- this.obstacles = getObstacleRects(this.problem);
4041
+ const getLabelOverlapCount = (path) => detectTraceLabelOverlap({
4042
+ traces: [{ ...this.initialTrace, tracePath: path }],
4043
+ netLabels: this.netLabelPlacements
4044
+ }).length;
4045
+ const candidateByPath = /* @__PURE__ */ new Map();
4046
+ for (const candidate of candidates) {
4047
+ const simplifiedCandidate = simplifyPath(candidate);
4048
+ candidateByPath.set(
4049
+ simplifiedCandidate.map((point) => `${point.x},${point.y}`).join(";"),
4050
+ simplifiedCandidate
4051
+ );
4052
+ }
4053
+ this.queuedCandidatePaths = [...candidateByPath.values()].sort((a, b) => {
4054
+ const pathLengthDifference = getPathLength(a) - getPathLength(b);
4055
+ if (Math.abs(pathLengthDifference) >= PATH_LENGTH_EPSILON) {
4056
+ return pathLengthDifference;
4057
+ }
4058
+ const overlapCountDifference = getLabelOverlapCount(a) - getLabelOverlapCount(b);
4059
+ if (overlapCountDifference !== 0) return overlapCountDifference;
4060
+ return a.length - b.length;
4061
+ });
4037
4062
  }
4038
4063
  _step() {
4039
4064
  if (this.queuedCandidatePaths.length === 0 || this._tried >= MAX_TRIES) {
@@ -4047,7 +4072,16 @@ var SingleOverlapSolver = class extends BaseSolver {
4047
4072
  traces: [{ ...this.initialTrace, tracePath: simplifiedPath }],
4048
4073
  netLabels: [this.label]
4049
4074
  }).length > 0;
4050
- if (!stillOverlapsLabel && !isPathCollidingWithObstacles(simplifiedPath, this.obstacles) && !doesPathCoincideWithTraces(simplifiedPath, this.tracesToAvoidOverlapping)) {
4075
+ const initialPath = simplifyPath(this.initialTrace.tracePath);
4076
+ const initialLabelOverlaps = detectTraceLabelOverlap({
4077
+ traces: [{ ...this.initialTrace, tracePath: initialPath }],
4078
+ netLabels: this.netLabelPlacements
4079
+ });
4080
+ const candidateLabelOverlaps = detectTraceLabelOverlap({
4081
+ traces: [{ ...this.initialTrace, tracePath: simplifiedPath }],
4082
+ netLabels: this.netLabelPlacements
4083
+ });
4084
+ if (!stillOverlapsLabel && candidateLabelOverlaps.length <= initialLabelOverlaps.length && !isPathCollidingWithObstacles(simplifiedPath, this.obstacles) && !doesPathCoincideWithTraces(simplifiedPath, this.tracesToAvoidOverlapping)) {
4051
4085
  this.solvedTracePath = simplifiedPath;
4052
4086
  this.solved = true;
4053
4087
  }
@@ -4070,7 +4104,7 @@ var SingleOverlapSolver = class extends BaseSolver {
4070
4104
  height: this.label.height,
4071
4105
  fill: "rgba(255, 0, 0, 0.2)"
4072
4106
  });
4073
- if (this.queuedCandidatePaths.length > 0) {
4107
+ if (!this.solvedTracePath && this.queuedCandidatePaths.length > 0) {
4074
4108
  graphics.lines.push({
4075
4109
  points: this.queuedCandidatePaths[0],
4076
4110
  strokeColor: "orange"
@@ -4154,6 +4188,7 @@ var OverlapAvoidanceStepSolver = class extends BaseSolver {
4154
4188
  allTraces;
4155
4189
  tracesToAvoidOverlapping;
4156
4190
  modifiedTraces = [];
4191
+ completedReroutes = [];
4157
4192
  PADDING_BUFFER = 0.1;
4158
4193
  detourCounts = /* @__PURE__ */ new Map();
4159
4194
  activeSubSolver = null;
@@ -4179,6 +4214,17 @@ var OverlapAvoidanceStepSolver = class extends BaseSolver {
4179
4214
  if (this.activeSubSolver.solved) {
4180
4215
  const solvedPath = this.activeSubSolver.solvedTracePath;
4181
4216
  if (solvedPath) {
4217
+ this.completedReroutes.push({
4218
+ initialTrace: {
4219
+ ...this.activeSubSolver.initialTrace,
4220
+ tracePath: this.activeSubSolver.initialTrace.tracePath.map(
4221
+ (point) => ({ ...point })
4222
+ )
4223
+ },
4224
+ reroutedTracePath: solvedPath.map((point) => ({ ...point })),
4225
+ label: this.activeSubSolver.label,
4226
+ detourCount: this.activeSubSolver.detourCount
4227
+ });
4182
4228
  const traceIndex = this.allTraces.findIndex(
4183
4229
  (t) => t.mspPairId === this.activeSubSolver.initialTrace.mspPairId
4184
4230
  );
@@ -4251,7 +4297,8 @@ var OverlapAvoidanceStepSolver = class extends BaseSolver {
4251
4297
  problem: this.inputProblem,
4252
4298
  paddingBuffer: this.PADDING_BUFFER,
4253
4299
  detourCount: detourCount2,
4254
- tracesToAvoidOverlapping: this.tracesToAvoidOverlapping
4300
+ tracesToAvoidOverlapping: this.tracesToAvoidOverlapping,
4301
+ netLabelPlacements: this.initialNetLabelPlacements
4255
4302
  });
4256
4303
  } else {
4257
4304
  const overlapId = `${traceToFix.mspPairId}-${labelToAvoid.globalConnNetId}`;
@@ -4287,7 +4334,8 @@ var OverlapAvoidanceStepSolver = class extends BaseSolver {
4287
4334
  problem: this.inputProblem,
4288
4335
  paddingBuffer: this.PADDING_BUFFER,
4289
4336
  detourCount: detourCount2,
4290
- tracesToAvoidOverlapping: this.tracesToAvoidOverlapping
4337
+ tracesToAvoidOverlapping: this.tracesToAvoidOverlapping,
4338
+ netLabelPlacements: this.initialNetLabelPlacements
4291
4339
  });
4292
4340
  } else {
4293
4341
  const overlapId = `${traceToFix.mspPairId}-${labelToAvoid.globalConnNetId}`;
@@ -4303,7 +4351,8 @@ var OverlapAvoidanceStepSolver = class extends BaseSolver {
4303
4351
  problem: this.inputProblem,
4304
4352
  paddingBuffer: this.PADDING_BUFFER,
4305
4353
  detourCount,
4306
- tracesToAvoidOverlapping: this.tracesToAvoidOverlapping
4354
+ tracesToAvoidOverlapping: this.tracesToAvoidOverlapping,
4355
+ netLabelPlacements: this.initialNetLabelPlacements
4307
4356
  });
4308
4357
  }
4309
4358
  }
@@ -4440,6 +4489,9 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
4440
4489
  const solvedTraces = this.subSolvers.flatMap((s) => s.getOutput().allTraces);
4441
4490
  return {
4442
4491
  traces: [...this.cleanTraces, ...solvedTraces],
4492
+ completedReroutes: this.subSolvers.flatMap(
4493
+ (solver) => solver.completedReroutes
4494
+ ),
4443
4495
  netLabelPlacements: this.labelMergingSolver?.getOutput().netLabelPlacements ?? this.netLabelPlacements
4444
4496
  };
4445
4497
  }
@@ -5527,7 +5579,7 @@ var segmentRunsAlongRectBoundary = (start, end, rect) => {
5527
5579
 
5528
5580
  // lib/solvers/Example28Solver/geometry.ts
5529
5581
  var getPathKey = (path) => path.map((point) => `${point.x},${point.y}`).join(";");
5530
- var getPathLength = (path) => {
5582
+ var getPathLength2 = (path) => {
5531
5583
  let length = 0;
5532
5584
  for (let i = 0; i < path.length - 1; i++) {
5533
5585
  length += Math.abs(path[i + 1].x - path[i].x) + Math.abs(path[i + 1].y - path[i].y);
@@ -5681,7 +5733,7 @@ var getTraceGeometryMetrics = (traces, allTraces) => ({
5681
5733
  ),
5682
5734
  visibleLength: getVisibleTraceLength(traces),
5683
5735
  pathLength: traces.reduce(
5684
- (sum, trace) => sum + getPathLength(trace.tracePath),
5736
+ (sum, trace) => sum + getPathLength2(trace.tracePath),
5685
5737
  0
5686
5738
  ),
5687
5739
  otherNetCrossings: countOtherNetCrossings(traces, allTraces)
@@ -6496,7 +6548,7 @@ var UntangleTraceSubsolver = class extends BaseSolver {
6496
6548
  candidate.traceId
6497
6549
  ).isColliding && (crossing.isInitialBundleCrossing || !candidate.collision.isColliding)
6498
6550
  ).sort(
6499
- (first, second) => Number(first.collision.isColliding) - Number(second.collision.isColliding) || getPathLength(first.path) - getPathLength(second.path)
6551
+ (first, second) => Number(first.collision.isColliding) - Number(second.collision.isColliding) || getPathLength2(first.path) - getPathLength2(second.path)
6500
6552
  );
6501
6553
  const bestCandidate = validCandidates[0];
6502
6554
  if (!bestCandidate) return false;
@@ -7405,7 +7457,7 @@ var scoreTracePath = ({
7405
7457
  labelHugDistance: getLabelHugDistance(tracePath, obstacleLabel),
7406
7458
  traceIntersections: countTraceIntersections(candidateTrace, outputTraces),
7407
7459
  chipBoundaryOverlap: getChipBoundaryOverlap(tracePath, chipObstacles),
7408
- pathLength: getPathLength(tracePath)
7460
+ pathLength: getPathLength2(tracePath)
7409
7461
  };
7410
7462
  };
7411
7463
  var countTraceIntersections = (trace, outputTraces) => {
@@ -10297,6 +10349,7 @@ var NetLabelTraceCollisionSolver = class extends BaseSolver {
10297
10349
  netLabelPlacements;
10298
10350
  outputTraces;
10299
10351
  outputNetLabelPlacements;
10352
+ completedReroutes = [];
10300
10353
  activeSubSolver = null;
10301
10354
  recentlyFailed = /* @__PURE__ */ new Set();
10302
10355
  detourCounts = /* @__PURE__ */ new Map();
@@ -10322,6 +10375,17 @@ var NetLabelTraceCollisionSolver = class extends BaseSolver {
10322
10375
  if (this.activeSubSolver.solved) {
10323
10376
  const solvedPath = this.activeSubSolver.solvedTracePath;
10324
10377
  if (solvedPath) {
10378
+ this.completedReroutes.push({
10379
+ initialTrace: {
10380
+ ...this.activeSubSolver.initialTrace,
10381
+ tracePath: this.activeSubSolver.initialTrace.tracePath.map(
10382
+ (point) => ({ ...point })
10383
+ )
10384
+ },
10385
+ reroutedTracePath: solvedPath.map((point) => ({ ...point })),
10386
+ label: this.activeSubSolver.label,
10387
+ detourCount: this.activeSubSolver.detourCount
10388
+ });
10325
10389
  const idx = this.outputTraces.findIndex(
10326
10390
  (t) => t.mspPairId === this.activeSubSolver.initialTrace.mspPairId
10327
10391
  );
@@ -10384,7 +10448,8 @@ var NetLabelTraceCollisionSolver = class extends BaseSolver {
10384
10448
  problem: this.inputProblem,
10385
10449
  paddingBuffer: PADDING_BUFFER,
10386
10450
  detourCount,
10387
- tracesToAvoidOverlapping: this.outputTraces
10451
+ tracesToAvoidOverlapping: this.outputTraces,
10452
+ netLabelPlacements: this.outputNetLabelPlacements
10388
10453
  });
10389
10454
  }
10390
10455
  /**
@@ -10416,6 +10481,7 @@ var NetLabelTraceCollisionSolver = class extends BaseSolver {
10416
10481
  getOutput() {
10417
10482
  return {
10418
10483
  traces: this.outputTraces,
10484
+ completedReroutes: this.completedReroutes,
10419
10485
  netLabelPlacements: this.outputNetLabelPlacements
10420
10486
  };
10421
10487
  }
@@ -10828,7 +10894,7 @@ var removeConsecutiveDuplicatePoints = (path) => {
10828
10894
  }
10829
10895
  return filteredPath;
10830
10896
  };
10831
- var getPathLength2 = (path) => {
10897
+ var getPathLength3 = (path) => {
10832
10898
  let pathLength = 0;
10833
10899
  for (let pointIndex = 0; pointIndex < path.length - 1; pointIndex++) {
10834
10900
  const startPoint = path[pointIndex];
@@ -10912,7 +10978,7 @@ var getPerimeterCandidates = ({
10912
10978
  );
10913
10979
  }
10914
10980
  return candidates.sort(
10915
- (firstPath, secondPath) => getPathLength2(firstPath) - getPathLength2(secondPath)
10981
+ (firstPath, secondPath) => getPathLength3(firstPath) - getPathLength3(secondPath)
10916
10982
  );
10917
10983
  };
10918
10984
  var getSegmentMidpoint = (startPoint, endPoint) => {
@@ -11017,7 +11083,7 @@ var getJunctionCandidates = ({
11017
11083
  }
11018
11084
  }
11019
11085
  return candidates.sort(
11020
- (firstPath, secondPath) => getPathLength2(firstPath) - getPathLength2(secondPath)
11086
+ (firstPath, secondPath) => getPathLength3(firstPath) - getPathLength3(secondPath)
11021
11087
  );
11022
11088
  };
11023
11089
  var pathCollidesWithObstacles = ({
@@ -11525,6 +11591,569 @@ orientation: ${label.orientation}`
11525
11591
  }
11526
11592
  };
11527
11593
 
11594
+ // lib/solvers/TraceElbowTransitionSimplificationSolver/generateElbowTransitionSimplificationCandidates.ts
11595
+ var isSimpleFiveSegmentElbow = (path) => {
11596
+ const simplifiedPath = simplifyPath(path);
11597
+ if (simplifiedPath.length !== 6) return false;
11598
+ const segmentIsHorizontal = simplifiedPath.slice(0, -1).map((point, index) => isHorizontal(point, simplifiedPath[index + 1]));
11599
+ return segmentIsHorizontal.every(
11600
+ (isHorizontalSegment, index) => index === 0 || isHorizontalSegment !== segmentIsHorizontal[index - 1]
11601
+ );
11602
+ };
11603
+ var generateSegmentShiftCandidates = ({
11604
+ trace,
11605
+ label,
11606
+ paddingBuffer,
11607
+ detourCount
11608
+ }) => {
11609
+ if (trace.globalConnNetId === label.globalConnNetId) return [];
11610
+ const path = simplifyPath(trace.tracePath);
11611
+ if (!isSimpleFiveSegmentElbow(path)) return [];
11612
+ const labelBounds = getRectBounds(label.center, label.width, label.height);
11613
+ const effectivePadding = paddingBuffer + detourCount * paddingBuffer;
11614
+ const paddedLabelBounds = {
11615
+ minX: labelBounds.minX - effectivePadding,
11616
+ maxX: labelBounds.maxX + effectivePadding,
11617
+ minY: labelBounds.minY - effectivePadding,
11618
+ maxY: labelBounds.maxY + effectivePadding
11619
+ };
11620
+ const candidates = [];
11621
+ for (let segmentIndex = 1; segmentIndex < path.length - 2; segmentIndex++) {
11622
+ const segmentStart = path[segmentIndex];
11623
+ const segmentEnd = path[segmentIndex + 1];
11624
+ if (!segmentIntersectsRect(segmentStart, segmentEnd, labelBounds)) continue;
11625
+ const isHorizontalSegment = isHorizontal(segmentStart, segmentEnd);
11626
+ const isVerticalSegment = isVertical(segmentStart, segmentEnd);
11627
+ if (!isHorizontalSegment && !isVerticalSegment) continue;
11628
+ const axis = isHorizontalSegment ? "y" : "x";
11629
+ const coordinates = isHorizontalSegment ? [paddedLabelBounds.minY, paddedLabelBounds.maxY] : [paddedLabelBounds.minX, paddedLabelBounds.maxX];
11630
+ for (const coordinate of coordinates) {
11631
+ const shiftedPath = shiftSegmentOrth(path, segmentIndex, axis, coordinate);
11632
+ if (shiftedPath) candidates.push(shiftedPath);
11633
+ }
11634
+ }
11635
+ return candidates;
11636
+ };
11637
+ var generateTransitionShiftCandidates = ({
11638
+ trace,
11639
+ label,
11640
+ paddingBuffer,
11641
+ detourCount
11642
+ }) => {
11643
+ const path = simplifyPath(trace.tracePath);
11644
+ if (!isSimpleFiveSegmentElbow(path)) return [];
11645
+ const labelBounds = getRectBounds(label.center, label.width, label.height);
11646
+ const effectivePadding = paddingBuffer + detourCount * paddingBuffer;
11647
+ const paddedLabelBounds = {
11648
+ minX: labelBounds.minX - effectivePadding,
11649
+ maxX: labelBounds.maxX + effectivePadding,
11650
+ minY: labelBounds.minY - effectivePadding,
11651
+ maxY: labelBounds.maxY + effectivePadding
11652
+ };
11653
+ const start = path[0];
11654
+ const end = path[path.length - 1];
11655
+ const middleSegmentIndex = 2;
11656
+ const candidates = [];
11657
+ for (let segmentIndex = 0; segmentIndex < path.length - 1; segmentIndex++) {
11658
+ const segmentStart = path[segmentIndex];
11659
+ const segmentEnd = path[segmentIndex + 1];
11660
+ if (!segmentIntersectsRect(segmentStart, segmentEnd, labelBounds)) continue;
11661
+ if (Math.abs(segmentIndex - middleSegmentIndex) !== 1) continue;
11662
+ const isHorizontalSegment = isHorizontal(segmentStart, segmentEnd);
11663
+ const isVerticalSegment = isVertical(segmentStart, segmentEnd);
11664
+ if (!isHorizontalSegment && !isVerticalSegment) continue;
11665
+ const axis = isHorizontalSegment ? "x" : "y";
11666
+ const min = isHorizontalSegment ? paddedLabelBounds.minX : paddedLabelBounds.minY;
11667
+ const max = isHorizontalSegment ? paddedLabelBounds.maxX : paddedLabelBounds.maxY;
11668
+ const startCoordinate = isHorizontalSegment ? start.x : start.y;
11669
+ const endCoordinate = isHorizontalSegment ? end.x : end.y;
11670
+ const corridorCoordinates = [];
11671
+ if (startCoordinate < min) {
11672
+ corridorCoordinates.push((startCoordinate + min) / 2);
11673
+ } else if (startCoordinate > max) {
11674
+ corridorCoordinates.push((startCoordinate + max) / 2);
11675
+ }
11676
+ if (endCoordinate < min) {
11677
+ corridorCoordinates.push((endCoordinate + min) / 2);
11678
+ } else if (endCoordinate > max) {
11679
+ corridorCoordinates.push((endCoordinate + max) / 2);
11680
+ }
11681
+ for (const coordinate of new Set(corridorCoordinates)) {
11682
+ const shiftedPath = shiftSegmentOrth(
11683
+ path,
11684
+ middleSegmentIndex,
11685
+ axis,
11686
+ coordinate
11687
+ );
11688
+ if (shiftedPath) candidates.push(shiftedPath);
11689
+ }
11690
+ }
11691
+ return candidates;
11692
+ };
11693
+ var generateElbowTransitionSimplificationCandidates = ({
11694
+ trace,
11695
+ label,
11696
+ netLabelPlacements,
11697
+ paddingBuffer,
11698
+ detourCount
11699
+ }) => {
11700
+ const transitionCandidates = generateTransitionShiftCandidates({
11701
+ trace,
11702
+ label,
11703
+ paddingBuffer,
11704
+ detourCount
11705
+ });
11706
+ return transitionCandidates.flatMap((tracePath) => {
11707
+ const shiftedTrace = { ...trace, tracePath };
11708
+ const shiftedOverlaps = detectTraceLabelOverlap({
11709
+ traces: [shiftedTrace],
11710
+ netLabels: netLabelPlacements
11711
+ });
11712
+ return shiftedOverlaps.flatMap(
11713
+ ({ label: shiftedLabel }) => generateSegmentShiftCandidates({
11714
+ trace: shiftedTrace,
11715
+ label: shiftedLabel,
11716
+ paddingBuffer,
11717
+ detourCount
11718
+ })
11719
+ );
11720
+ });
11721
+ };
11722
+
11723
+ // lib/solvers/TraceElbowTransitionSimplificationSolver/TraceElbowTransitionSimplificationSolver.ts
11724
+ var PATH_LENGTH_EPSILON2 = 1e-9;
11725
+ var getPathLength4 = (points) => points.slice(1).reduce((length, point, pointIndex) => {
11726
+ const previousPoint = points[pointIndex];
11727
+ return length + Math.abs(point.x - previousPoint.x) + Math.abs(point.y - previousPoint.y);
11728
+ }, 0);
11729
+ var TraceElbowTransitionSimplificationSolver = class extends BaseSolver {
11730
+ input;
11731
+ outputTraces;
11732
+ traceIdQueue;
11733
+ obstacles;
11734
+ constructor(input) {
11735
+ super();
11736
+ this.input = input;
11737
+ this.outputTraces = [...input.traces];
11738
+ const reroutedTraceIds = new Set(
11739
+ input.completedReroutes.map(
11740
+ (completedReroute) => completedReroute.initialTrace.mspPairId
11741
+ )
11742
+ );
11743
+ this.traceIdQueue = input.traces.map((trace) => trace.mspPairId).filter((traceId) => reroutedTraceIds.has(traceId));
11744
+ this.obstacles = getObstacleRects(input.inputProblem);
11745
+ }
11746
+ _step() {
11747
+ const traceId = this.traceIdQueue.shift();
11748
+ if (!traceId) {
11749
+ this.solved = true;
11750
+ return;
11751
+ }
11752
+ const traceIndex = this.outputTraces.findIndex(
11753
+ (trace2) => trace2.mspPairId === traceId
11754
+ );
11755
+ const trace = this.outputTraces[traceIndex];
11756
+ const tracePath = simplifyPath(trace.tracePath);
11757
+ const initialOverlaps = detectTraceLabelOverlap({
11758
+ traces: [{ ...trace, tracePath }],
11759
+ netLabels: this.input.netLabelPlacements
11760
+ });
11761
+ const otherNetTraces = this.outputTraces.filter(
11762
+ (otherTrace) => otherTrace.mspPairId !== trace.mspPairId && otherTrace.globalConnNetId !== trace.globalConnNetId
11763
+ );
11764
+ const candidateByPath = /* @__PURE__ */ new Map();
11765
+ const completedReroutes = this.input.completedReroutes.filter(
11766
+ (completedReroute) => completedReroute.initialTrace.mspPairId === trace.mspPairId
11767
+ );
11768
+ for (const completedReroute of completedReroutes) {
11769
+ const initialReroutePath = simplifyPath(
11770
+ completedReroute.initialTrace.tracePath
11771
+ );
11772
+ const reroutedPath = simplifyPath(completedReroute.reroutedTracePath);
11773
+ const initialRerouteOverlapCount = detectTraceLabelOverlap({
11774
+ traces: [
11775
+ { ...completedReroute.initialTrace, tracePath: initialReroutePath }
11776
+ ],
11777
+ netLabels: this.input.netLabelPlacements
11778
+ }).length;
11779
+ const candidates = generateElbowTransitionSimplificationCandidates({
11780
+ trace: completedReroute.initialTrace,
11781
+ label: completedReroute.label,
11782
+ netLabelPlacements: this.input.netLabelPlacements,
11783
+ paddingBuffer: this.input.paddingBuffer,
11784
+ detourCount: completedReroute.detourCount
11785
+ });
11786
+ for (const candidate of candidates) {
11787
+ const simplifiedCandidate = simplifyPath(candidate);
11788
+ const candidateTrace = {
11789
+ ...completedReroute.initialTrace,
11790
+ tracePath: simplifiedCandidate
11791
+ };
11792
+ const candidateOverlapCount = detectTraceLabelOverlap({
11793
+ traces: [candidateTrace],
11794
+ netLabels: this.input.netLabelPlacements
11795
+ }).length;
11796
+ const isSimplerEquivalentReroute = candidateOverlapCount < initialRerouteOverlapCount && Math.abs(
11797
+ getPathLength4(simplifiedCandidate) - getPathLength4(reroutedPath)
11798
+ ) < PATH_LENGTH_EPSILON2 && simplifiedCandidate.length < reroutedPath.length && preservesLabelAnchors(
11799
+ this.input.netLabelPlacements,
11800
+ [completedReroute.initialTrace],
11801
+ [candidateTrace]
11802
+ );
11803
+ if (isSimplerEquivalentReroute) {
11804
+ candidateByPath.set(
11805
+ simplifiedCandidate.map((point) => `${point.x},${point.y}`).join(";"),
11806
+ simplifiedCandidate
11807
+ );
11808
+ }
11809
+ }
11810
+ }
11811
+ const initialOverlapIds = new Set(
11812
+ initialOverlaps.map(
11813
+ ({ label }) => `${label.globalConnNetId}:${label.netId}`
11814
+ )
11815
+ );
11816
+ const initialPathLength = getPathLength4(tracePath);
11817
+ const validCandidates = [...candidateByPath.values()].filter(
11818
+ (candidatePath) => {
11819
+ const candidateTrace = { ...trace, tracePath: candidatePath };
11820
+ const candidateOverlaps = detectTraceLabelOverlap({
11821
+ traces: [candidateTrace],
11822
+ netLabels: this.input.netLabelPlacements
11823
+ });
11824
+ const candidateOnlyKeepsExistingOverlaps = candidateOverlaps.every(
11825
+ ({ label }) => initialOverlapIds.has(`${label.globalConnNetId}:${label.netId}`)
11826
+ );
11827
+ const reducesCollisions = candidateOverlaps.length < initialOverlaps.length;
11828
+ const simplifiesGeometry = candidateOverlaps.length === initialOverlaps.length && getPathLength4(candidatePath) <= initialPathLength + PATH_LENGTH_EPSILON2 && candidatePath.length < tracePath.length;
11829
+ return candidateOnlyKeepsExistingOverlaps && (reducesCollisions || simplifiesGeometry) && preservesLabelAnchors(
11830
+ this.input.netLabelPlacements,
11831
+ [trace],
11832
+ [candidateTrace]
11833
+ ) && !isPathCollidingWithObstacles(candidatePath, this.obstacles) && !doesPathCoincideWithTraces(candidatePath, otherNetTraces);
11834
+ }
11835
+ );
11836
+ const getOverlapCount = (candidatePath) => detectTraceLabelOverlap({
11837
+ traces: [{ ...trace, tracePath: candidatePath }],
11838
+ netLabels: this.input.netLabelPlacements
11839
+ }).length;
11840
+ validCandidates.sort((a, b) => {
11841
+ const overlapDifference = getOverlapCount(a) - getOverlapCount(b);
11842
+ if (overlapDifference !== 0) return overlapDifference;
11843
+ return getPathLength4(a) - getPathLength4(b) || a.length - b.length;
11844
+ });
11845
+ const bestCandidate = validCandidates[0];
11846
+ if (!bestCandidate) return;
11847
+ this.outputTraces[traceIndex] = { ...trace, tracePath: bestCandidate };
11848
+ this.stats.simplifiedTraceCount = (this.stats.simplifiedTraceCount ?? 0) + 1;
11849
+ }
11850
+ getOutput() {
11851
+ return {
11852
+ traces: this.outputTraces,
11853
+ netLabelPlacements: this.input.netLabelPlacements
11854
+ };
11855
+ }
11856
+ visualize() {
11857
+ const graphics = visualizeInputProblem(this.input.inputProblem);
11858
+ graphics.lines ??= [];
11859
+ for (const trace of this.outputTraces) {
11860
+ graphics.lines.push({ points: trace.tracePath, strokeColor: "purple" });
11861
+ }
11862
+ return graphics;
11863
+ }
11864
+ };
11865
+
11866
+ // lib/solvers/InlineNetLabelSolver/getAxisAlignedSegments.ts
11867
+ var getAxisAlignedSegments = (path, epsilon = 1e-6) => {
11868
+ const segments = [];
11869
+ let runStart = null;
11870
+ let runAxis = null;
11871
+ let runSign = 0;
11872
+ const closeRun = (runEnd) => {
11873
+ if (runStart && runAxis) {
11874
+ const length = runAxis === "x" ? Math.abs(runEnd.x - runStart.x) : Math.abs(runEnd.y - runStart.y);
11875
+ if (length > epsilon) {
11876
+ segments.push({ start: runStart, end: runEnd, axis: runAxis, length });
11877
+ }
11878
+ }
11879
+ runStart = null;
11880
+ runAxis = null;
11881
+ runSign = 0;
11882
+ };
11883
+ for (let i = 0; i < path.length - 1; i++) {
11884
+ const a = path[i];
11885
+ const b = path[i + 1];
11886
+ const dx = b.x - a.x;
11887
+ const dy = b.y - a.y;
11888
+ if (Math.abs(dx) <= epsilon && Math.abs(dy) <= epsilon) continue;
11889
+ const axis = Math.abs(dy) <= epsilon ? "x" : Math.abs(dx) <= epsilon ? "y" : null;
11890
+ if (!axis) {
11891
+ closeRun(a);
11892
+ continue;
11893
+ }
11894
+ const sign = Math.sign(axis === "x" ? dx : dy);
11895
+ if (runStart && runAxis === axis && runSign === sign) continue;
11896
+ closeRun(a);
11897
+ runStart = a;
11898
+ runAxis = axis;
11899
+ runSign = sign;
11900
+ }
11901
+ if (path.length >= 2) {
11902
+ closeRun(path[path.length - 1]);
11903
+ }
11904
+ return segments.sort((a, b) => b.length - a.length);
11905
+ };
11906
+
11907
+ // lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts
11908
+ var DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
11909
+ var INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
11910
+ var MIN_INLINE_NET_LABEL_SEGMENT_RATIO = 0.5;
11911
+ var getPinPairKey2 = (pinIds) => [...pinIds].sort().join("::");
11912
+ var InlineNetLabelSolver = class extends BaseSolver {
11913
+ inputProblem;
11914
+ traces;
11915
+ inputNetLabelPlacements;
11916
+ inlineNetLabelPlacements = [];
11917
+ /** Direct connections that opted in, still waiting to be processed */
11918
+ queuedDirectConnections;
11919
+ tracesByPinPairKey;
11920
+ constructor(input) {
11921
+ super();
11922
+ this.inputProblem = input.inputProblem;
11923
+ this.traces = input.traces;
11924
+ this.inputNetLabelPlacements = input.netLabelPlacements;
11925
+ this.queuedDirectConnections = this.inputProblem.directConnections.filter(
11926
+ (dc) => dc.allowInlineNetLabel && dc.netId
11927
+ );
11928
+ this.tracesByPinPairKey = /* @__PURE__ */ new Map();
11929
+ for (const trace of this.traces) {
11930
+ const key = getPinPairKey2(trace.pins.map((p) => p.pinId));
11931
+ const existing = this.tracesByPinPairKey.get(key);
11932
+ if (existing) {
11933
+ existing.push(trace);
11934
+ } else {
11935
+ this.tracesByPinPairKey.set(key, [trace]);
11936
+ }
11937
+ }
11938
+ }
11939
+ getConstructorParams() {
11940
+ return [
11941
+ {
11942
+ inputProblem: this.inputProblem,
11943
+ traces: this.traces,
11944
+ netLabelPlacements: this.inputNetLabelPlacements
11945
+ }
11946
+ ];
11947
+ }
11948
+ _step() {
11949
+ const directConnection = this.queuedDirectConnections.shift();
11950
+ if (!directConnection) {
11951
+ this.solved = true;
11952
+ this.stats.inlineNetLabelCount = this.inlineNetLabelPlacements.length;
11953
+ return;
11954
+ }
11955
+ const placement = this.computeInlinePlacement(directConnection);
11956
+ if (placement) {
11957
+ this.inlineNetLabelPlacements.push(placement);
11958
+ }
11959
+ }
11960
+ computeInlinePlacement(directConnection) {
11961
+ const traces = this.tracesByPinPairKey.get(getPinPairKey2(directConnection.pinIds)) ?? [];
11962
+ if (traces.length === 0) return null;
11963
+ const trace = traces[0];
11964
+ const segments = getAxisAlignedSegments(trace.tracePath);
11965
+ if (segments.length === 0) return null;
11966
+ const height = directConnection.inlineNetLabelHeight ?? DEFAULT_INLINE_NET_LABEL_HEIGHT;
11967
+ const width = directConnection.inlineNetLabelWidth ?? directConnection.netLabelWidth ?? estimateInlineNetLabelWidth(directConnection.netId, height);
11968
+ const offset = height / 2 + INLINE_NET_LABEL_TRACE_MARGIN;
11969
+ const usableSegments = segments.filter(
11970
+ (segment) => segment.length >= width * MIN_INLINE_NET_LABEL_SEGMENT_RATIO
11971
+ ).sort((a, b) => {
11972
+ const aFits = a.length >= width;
11973
+ const bFits = b.length >= width;
11974
+ if (aFits !== bFits) return aFits ? -1 : 1;
11975
+ return b.length - a.length;
11976
+ });
11977
+ for (const segment of usableSegments) {
11978
+ const sides = segment.axis === "x" ? ["y+", "y-"] : ["x-", "x+"];
11979
+ for (const side of sides) {
11980
+ for (const anchorPoint of getAnchorCandidates(segment, width)) {
11981
+ const center = side === "y+" ? { x: anchorPoint.x, y: anchorPoint.y + offset } : side === "y-" ? { x: anchorPoint.x, y: anchorPoint.y - offset } : side === "x-" ? { x: anchorPoint.x - offset, y: anchorPoint.y } : { x: anchorPoint.x + offset, y: anchorPoint.y };
11982
+ const halfAlong = width / 2;
11983
+ const halfAcross = height / 2;
11984
+ const bounds = segment.axis === "x" ? {
11985
+ minX: center.x - halfAlong,
11986
+ maxX: center.x + halfAlong,
11987
+ minY: center.y - halfAcross,
11988
+ maxY: center.y + halfAcross
11989
+ } : {
11990
+ minX: center.x - halfAcross,
11991
+ maxX: center.x + halfAcross,
11992
+ minY: center.y - halfAlong,
11993
+ maxY: center.y + halfAlong
11994
+ };
11995
+ if (this.isObstructed(bounds, trace)) continue;
11996
+ return {
11997
+ globalConnNetId: trace.globalConnNetId,
11998
+ netId: directConnection.netId,
11999
+ mspPairId: trace.mspPairId,
12000
+ pinIds: [...directConnection.pinIds],
12001
+ axis: segment.axis,
12002
+ anchorPoint,
12003
+ center,
12004
+ width,
12005
+ height,
12006
+ side
12007
+ };
12008
+ }
12009
+ }
12010
+ }
12011
+ return null;
12012
+ }
12013
+ /**
12014
+ * An inline label may not sit on top of a chip, a component's text, or a
12015
+ * trace belonging to another net.
12016
+ */
12017
+ isObstructed(bounds, ownTrace) {
12018
+ for (const chip of this.inputProblem.chips) {
12019
+ const chipBounds = {
12020
+ minX: chip.center.x - chip.width / 2,
12021
+ maxX: chip.center.x + chip.width / 2,
12022
+ minY: chip.center.y - chip.height / 2,
12023
+ maxY: chip.center.y + chip.height / 2
12024
+ };
12025
+ if (boundsOverlap(bounds, chipBounds)) return true;
12026
+ }
12027
+ for (const textBox of this.inputProblem.textBoxes ?? []) {
12028
+ if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true;
12029
+ }
12030
+ for (const trace of this.traces) {
12031
+ if (trace.mspPairId === ownTrace.mspPairId) continue;
12032
+ if (trace.globalConnNetId === ownTrace.globalConnNetId) continue;
12033
+ if (doesPathIntersectBounds(trace.tracePath, bounds)) return true;
12034
+ }
12035
+ return false;
12036
+ }
12037
+ /**
12038
+ * Net label placements superseded by an inline label. A net gets one label or
12039
+ * the other, never both.
12040
+ */
12041
+ getSupersededNetLabelKeys() {
12042
+ const keys = /* @__PURE__ */ new Set();
12043
+ for (const placement of this.inlineNetLabelPlacements) {
12044
+ keys.add(placement.globalConnNetId);
12045
+ }
12046
+ return keys;
12047
+ }
12048
+ getOutput() {
12049
+ const superseded = this.getSupersededNetLabelKeys();
12050
+ return {
12051
+ traces: this.traces,
12052
+ netLabelPlacements: this.inputNetLabelPlacements.filter(
12053
+ (placement) => !superseded.has(placement.globalConnNetId)
12054
+ ),
12055
+ inlineNetLabelPlacements: this.inlineNetLabelPlacements
12056
+ };
12057
+ }
12058
+ visualize() {
12059
+ const graphics = visualizeInputProblem(this.inputProblem);
12060
+ graphics.lines ??= [];
12061
+ graphics.rects ??= [];
12062
+ graphics.points ??= [];
12063
+ graphics.texts ??= [];
12064
+ for (const trace of this.traces) {
12065
+ graphics.lines.push({
12066
+ points: trace.tracePath,
12067
+ strokeColor: "purple"
12068
+ });
12069
+ }
12070
+ const { netLabelPlacements } = this.getOutput();
12071
+ for (const label of netLabelPlacements) {
12072
+ graphics.rects.push({
12073
+ center: label.center,
12074
+ width: label.width,
12075
+ height: label.height,
12076
+ fill: getColorFromString(label.globalConnNetId, 0.35),
12077
+ strokeColor: getColorFromString(label.globalConnNetId, 0.9),
12078
+ label: `netId: ${label.netId}
12079
+ globalConnNetId: ${label.globalConnNetId}`
12080
+ });
12081
+ graphics.points.push({
12082
+ x: label.anchorPoint.x,
12083
+ y: label.anchorPoint.y,
12084
+ color: getColorFromString(label.globalConnNetId, 0.9),
12085
+ label: `anchorPoint
12086
+ orientation: ${label.orientation}`
12087
+ });
12088
+ }
12089
+ for (const inlineLabel of this.inlineNetLabelPlacements) {
12090
+ const isHorizontal4 = inlineLabel.axis === "x";
12091
+ graphics.rects.push({
12092
+ center: inlineLabel.center,
12093
+ width: isHorizontal4 ? inlineLabel.width : inlineLabel.height,
12094
+ height: isHorizontal4 ? inlineLabel.height : inlineLabel.width,
12095
+ fill: getColorFromString(inlineLabel.globalConnNetId, 0.35),
12096
+ strokeColor: "green",
12097
+ label: [
12098
+ `INLINE netId: ${inlineLabel.netId}`,
12099
+ `axis: ${inlineLabel.axis}`,
12100
+ `side: ${inlineLabel.side}`
12101
+ ].join("\n")
12102
+ });
12103
+ graphics.texts.push({
12104
+ x: inlineLabel.center.x,
12105
+ y: inlineLabel.center.y,
12106
+ text: inlineLabel.netId ?? "",
12107
+ color: "green",
12108
+ fontSize: inlineLabel.height,
12109
+ anchorSide: "center"
12110
+ });
12111
+ graphics.points.push({
12112
+ x: inlineLabel.anchorPoint.x,
12113
+ y: inlineLabel.anchorPoint.y,
12114
+ color: "green",
12115
+ label: `inline anchor
12116
+ ${inlineLabel.netId}`
12117
+ });
12118
+ }
12119
+ return graphics;
12120
+ }
12121
+ };
12122
+ var estimateInlineNetLabelWidth = (text, fontSize = DEFAULT_INLINE_NET_LABEL_HEIGHT) => {
12123
+ const fontScale = fontSize / 0.18;
12124
+ return text.length * 0.12 * fontScale + 0.12 * fontScale;
12125
+ };
12126
+ var getAnchorCandidates = (segment, labelWidth, step = 0.1) => {
12127
+ const along = segment.axis === "x" ? "x" : "y";
12128
+ const start = segment.start[along];
12129
+ const end = segment.end[along];
12130
+ const mid = (start + end) / 2;
12131
+ const direction = Math.sign(end - start) || 1;
12132
+ const pointAt = (value) => segment.axis === "x" ? { x: value, y: segment.start.y } : { x: segment.start.x, y: segment.start.y + (value - start) };
12133
+ const slack = segment.length - labelWidth;
12134
+ if (slack <= 0) return [pointAt(mid)];
12135
+ const offsets = [0];
12136
+ for (let offset = step; offset <= slack / 2 + 1e-9; offset += step) {
12137
+ offsets.push(offset, -offset);
12138
+ }
12139
+ offsets.push(slack / 2, -slack / 2);
12140
+ return offsets.map((offset) => pointAt(mid + offset * direction));
12141
+ };
12142
+ var doesPathIntersectBounds = (path, bounds) => {
12143
+ for (let i = 0; i < path.length - 1; i++) {
12144
+ const a = path[i];
12145
+ const b = path[i + 1];
12146
+ const segmentBounds = {
12147
+ minX: Math.min(a.x, b.x),
12148
+ maxX: Math.max(a.x, b.x),
12149
+ minY: Math.min(a.y, b.y),
12150
+ maxY: Math.max(a.y, b.y)
12151
+ };
12152
+ if (boundsOverlap(segmentBounds, bounds)) return true;
12153
+ }
12154
+ return false;
12155
+ };
12156
+
11528
12157
  // lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts
11529
12158
  function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
11530
12159
  return {
@@ -11555,7 +12184,11 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
11555
12184
  netLabelTraceCollisionSolver;
11556
12185
  traceCleanupSolver2;
11557
12186
  netLabelNetLabelCollisionSolver;
12187
+ traceElbowTransitionSimplificationSolver;
12188
+ preAlignmentTraceElbowTransitionSimplificationSolver;
12189
+ finalTraceElbowTransitionSimplificationSolver;
11558
12190
  sameNetJunctionAlignmentSolver;
12191
+ inlineNetLabelSolver;
11559
12192
  startTimeOfPhase;
11560
12193
  endTimeOfPhase;
11561
12194
  timeSpentOnPhase;
@@ -11676,8 +12309,24 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
11676
12309
  ];
11677
12310
  }
11678
12311
  ),
12312
+ definePipelineStep(
12313
+ "traceElbowTransitionSimplificationSolver",
12314
+ TraceElbowTransitionSimplificationSolver,
12315
+ (instance) => {
12316
+ const overlapAvoidanceOutput = instance.traceLabelOverlapAvoidanceSolver.getOutput();
12317
+ return [
12318
+ {
12319
+ inputProblem: instance.inputProblem,
12320
+ traces: overlapAvoidanceOutput.traces,
12321
+ completedReroutes: overlapAvoidanceOutput.completedReroutes,
12322
+ netLabelPlacements: instance.traceLabelOverlapAvoidanceSolver.netLabelPlacements,
12323
+ paddingBuffer: 0.1
12324
+ }
12325
+ ];
12326
+ }
12327
+ ),
11679
12328
  definePipelineStep("traceCleanupSolver", TraceCleanupSolver, (instance) => {
11680
- const prevSolverOutput = instance.traceLabelOverlapAvoidanceSolver.getOutput();
12329
+ const prevSolverOutput = instance.traceElbowTransitionSimplificationSolver.getOutput();
11681
12330
  const traces = prevSolverOutput.traces;
11682
12331
  const labelMergingOutput = instance.traceLabelOverlapAvoidanceSolver.labelMergingSolver.getOutput();
11683
12332
  return [
@@ -11779,11 +12428,27 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
11779
12428
  }
11780
12429
  ]
11781
12430
  ),
12431
+ definePipelineStep(
12432
+ "preAlignmentTraceElbowTransitionSimplificationSolver",
12433
+ TraceElbowTransitionSimplificationSolver,
12434
+ (instance) => {
12435
+ const collisionOutput = instance.preAlignmentNetLabelTraceCollisionSolver.getOutput();
12436
+ return [
12437
+ {
12438
+ inputProblem: instance.inputProblem,
12439
+ traces: collisionOutput.traces,
12440
+ completedReroutes: collisionOutput.completedReroutes,
12441
+ netLabelPlacements: collisionOutput.netLabelPlacements,
12442
+ paddingBuffer: 0.1
12443
+ }
12444
+ ];
12445
+ }
12446
+ ),
11782
12447
  definePipelineStep(
11783
12448
  "traceCleanupSolver2",
11784
12449
  TraceCleanupSolver,
11785
12450
  (instance) => {
11786
- const collisionOutput = instance.preAlignmentNetLabelTraceCollisionSolver.getOutput();
12451
+ const collisionOutput = instance.preAlignmentTraceElbowTransitionSimplificationSolver.getOutput();
11787
12452
  const labelMergingOutput = instance.traceLabelOverlapAvoidanceSolver.labelMergingSolver.getOutput();
11788
12453
  return [
11789
12454
  {
@@ -11836,16 +12501,35 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
11836
12501
  ];
11837
12502
  }
11838
12503
  ),
12504
+ definePipelineStep(
12505
+ "finalTraceElbowTransitionSimplificationSolver",
12506
+ TraceElbowTransitionSimplificationSolver,
12507
+ (instance) => {
12508
+ const collisionOutput = instance.netLabelTraceCollisionSolver.getOutput();
12509
+ return [
12510
+ {
12511
+ inputProblem: instance.inputProblem,
12512
+ traces: collisionOutput.traces,
12513
+ completedReroutes: collisionOutput.completedReroutes,
12514
+ netLabelPlacements: collisionOutput.netLabelPlacements,
12515
+ paddingBuffer: 0.1
12516
+ }
12517
+ ];
12518
+ }
12519
+ ),
11839
12520
  definePipelineStep(
11840
12521
  "netLabelNetLabelCollisionSolver",
11841
12522
  NetLabelNetLabelCollisionSolver,
11842
- (instance) => [
11843
- {
11844
- inputProblem: instance.inputProblem,
11845
- traces: instance.netLabelTraceCollisionSolver.getOutput().traces,
11846
- netLabelPlacements: instance.netLabelTraceCollisionSolver.getOutput().netLabelPlacements
11847
- }
11848
- ]
12523
+ (instance) => {
12524
+ const simplificationOutput = instance.finalTraceElbowTransitionSimplificationSolver.getOutput();
12525
+ return [
12526
+ {
12527
+ inputProblem: instance.inputProblem,
12528
+ traces: simplificationOutput.traces,
12529
+ netLabelPlacements: simplificationOutput.netLabelPlacements
12530
+ }
12531
+ ];
12532
+ }
11849
12533
  ),
11850
12534
  definePipelineStep(
11851
12535
  "sameNetJunctionAlignmentSolver",
@@ -11860,6 +12544,20 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
11860
12544
  }
11861
12545
  ];
11862
12546
  }
12547
+ ),
12548
+ definePipelineStep(
12549
+ "inlineNetLabelSolver",
12550
+ InlineNetLabelSolver,
12551
+ (instance) => {
12552
+ const junctionOutput = instance.sameNetJunctionAlignmentSolver.getOutput();
12553
+ return [
12554
+ {
12555
+ inputProblem: instance.inputProblem,
12556
+ traces: junctionOutput.traces,
12557
+ netLabelPlacements: junctionOutput.netLabelPlacements
12558
+ }
12559
+ ];
12560
+ }
11863
12561
  )
11864
12562
  ];
11865
12563
  constructor(inputProblem, opts) {
@@ -11973,6 +12671,11 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
11973
12671
  }
11974
12672
  };
11975
12673
  export {
12674
+ DEFAULT_INLINE_NET_LABEL_HEIGHT,
12675
+ INLINE_NET_LABEL_TRACE_MARGIN,
12676
+ InlineNetLabelSolver,
12677
+ MIN_INLINE_NET_LABEL_SEGMENT_RATIO,
11976
12678
  SchematicTracePipelineSolver,
11977
- SchematicTraceSingleLineSolver2
12679
+ SchematicTraceSingleLineSolver2,
12680
+ estimateInlineNetLabelWidth
11978
12681
  };