@tscircuit/schematic-trace-solver 0.0.141 → 0.0.142

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
@@ -115,6 +115,16 @@ interface InputNetConnection {
115
115
  pinIds: Array<PinId>;
116
116
  netLabelWidth?: number;
117
117
  netLabelHeight?: number;
118
+ /**
119
+ * When true, a named single-pin net may be drawn as a short outward trace
120
+ * stub with its net name placed inline. Multi-pin net connections retain the
121
+ * regular anchored-label behavior.
122
+ */
123
+ allowInlineNetLabel?: boolean;
124
+ /** Extent of the inline text along the generated trace stub. */
125
+ inlineNetLabelWidth?: number;
126
+ /** Height of the inline text perpendicular to the generated trace stub. */
127
+ inlineNetLabelHeight?: number;
118
128
  }
119
129
  interface InputProblem {
120
130
  chips: Array<InputChip>;
@@ -1186,8 +1196,13 @@ declare const INLINE_NET_LABEL_MAX_SPAN_JOG = 0.4;
1186
1196
  interface InlineNetLabelPlacement {
1187
1197
  globalConnNetId: string;
1188
1198
  netId?: string;
1189
- mspPairId: string;
1199
+ mspPairId?: string;
1190
1200
  pinIds: PinId[];
1201
+ /**
1202
+ * A generated single-ended trace stub. Present only for an eligible
1203
+ * single-pin net connection; routed point-to-point traces omit it.
1204
+ */
1205
+ stubTracePath?: [Point, Point];
1191
1206
  /** Axis the text runs along: "x" reads left-to-right, "y" reads bottom-to-top */
1192
1207
  axis: "x" | "y";
1193
1208
  /** Midpoint of the trace segment the label is attached to */
@@ -1224,10 +1239,20 @@ declare class InlineNetLabelSolver extends BaseSolver {
1224
1239
  inlineNetLabelPlacements: InlineNetLabelPlacement[];
1225
1240
  /** Direct connections that opted in, still waiting to be processed */
1226
1241
  queuedDirectConnections: InputDirectConnection[];
1242
+ /** Single-pin net connections that opted in, still waiting to be processed */
1243
+ queuedPortOnlyNetConnections: InputNetConnection[];
1227
1244
  private tracesByPinPairKey;
1245
+ private hasAlignedPortOnlyStubs;
1228
1246
  constructor(input: InlineNetLabelSolverInput);
1229
1247
  getConstructorParams(): [InlineNetLabelSolverInput];
1230
1248
  _step(): void;
1249
+ /**
1250
+ * Converts a conventional port-only anchored placement into an inline label
1251
+ * on a generated outward stub. The stub follows the pin's true facing
1252
+ * direction; an anchored label may finish in another direction after an
1253
+ * elbow, which is not the direction a terminal stub should leave the pin.
1254
+ */
1255
+ private computePortOnlyInlinePlacement;
1231
1256
  private computeInlinePlacement;
1232
1257
  /**
1233
1258
  * Places the label over the whole route when the route is straight except
@@ -1246,6 +1271,7 @@ declare class InlineNetLabelSolver extends BaseSolver {
1246
1271
  * the other, never both.
1247
1272
  */
1248
1273
  private getSupersededNetLabelKeys;
1274
+ private getOutputTraces;
1249
1275
  getOutput(): {
1250
1276
  traces: SolvedTracePath[];
1251
1277
  netLabelPlacements: NetLabelPlacement[];
package/dist/index.js CHANGED
@@ -12576,6 +12576,154 @@ var getAxisAlignedSegments = (path, epsilon = 1e-6) => {
12576
12576
  return segments.sort((a, b) => b.length - a.length);
12577
12577
  };
12578
12578
 
12579
+ // lib/solvers/InlineNetLabelSolver/alignPortOnlyInlineNetLabelStubs.ts
12580
+ var getStubDirection = (path) => {
12581
+ const [start, end] = path;
12582
+ if (Math.abs(end.x - start.x) >= Math.abs(end.y - start.y)) {
12583
+ return end.x >= start.x ? "x+" : "x-";
12584
+ }
12585
+ return end.y >= start.y ? "y+" : "y-";
12586
+ };
12587
+ var getStubLength = (path) => {
12588
+ const [start, end] = path;
12589
+ return Math.abs(end.x - start.x) + Math.abs(end.y - start.y);
12590
+ };
12591
+ var getLabelBounds2 = (placement) => {
12592
+ const isVertical5 = placement.axis === "y";
12593
+ const width = isVertical5 ? placement.height : placement.width;
12594
+ const height = isVertical5 ? placement.width : placement.height;
12595
+ return {
12596
+ minX: placement.center.x - width / 2,
12597
+ maxX: placement.center.x + width / 2,
12598
+ minY: placement.center.y - height / 2,
12599
+ maxY: placement.center.y + height / 2
12600
+ };
12601
+ };
12602
+ var getPathBounds = (path) => ({
12603
+ minX: Math.min(...path.map((point) => point.x)),
12604
+ maxX: Math.max(...path.map((point) => point.x)),
12605
+ minY: Math.min(...path.map((point) => point.y)),
12606
+ maxY: Math.max(...path.map((point) => point.y))
12607
+ });
12608
+ var doesPathIntersectBounds = (path, bounds) => {
12609
+ for (let index = 0; index < path.length - 1; index++) {
12610
+ const segmentBounds = getPathBounds([path[index], path[index + 1]]);
12611
+ if (boundsOverlap(segmentBounds, bounds)) return true;
12612
+ }
12613
+ return false;
12614
+ };
12615
+ var resizeStub = (placement, direction, targetLength) => {
12616
+ const [start] = placement.stubTracePath;
12617
+ const end = direction === "x+" ? { x: start.x + targetLength, y: start.y } : direction === "x-" ? { x: start.x - targetLength, y: start.y } : direction === "y+" ? { x: start.x, y: start.y + targetLength } : { x: start.x, y: start.y - targetLength };
12618
+ const anchorPoint = {
12619
+ x: (start.x + end.x) / 2,
12620
+ y: (start.y + end.y) / 2
12621
+ };
12622
+ return {
12623
+ ...placement,
12624
+ stubTracePath: [start, end],
12625
+ anchorPoint,
12626
+ // Extending a short row only adds wire at its free end. Keep the label
12627
+ // itself next to the pin so terminal labels can be start/end aligned and
12628
+ // collision checks continue to describe the rendered text box.
12629
+ center: placement.center
12630
+ };
12631
+ };
12632
+ var alignPortOnlyInlineNetLabelStubs = ({
12633
+ placements,
12634
+ inputProblem,
12635
+ traces,
12636
+ netLabelPlacements
12637
+ }) => {
12638
+ const chipIdByPinId = /* @__PURE__ */ new Map();
12639
+ for (const chip of inputProblem.chips) {
12640
+ for (const pin of chip.pins) chipIdByPinId.set(pin.pinId, chip.chipId);
12641
+ }
12642
+ const groups = /* @__PURE__ */ new Map();
12643
+ for (const [placementIndex, placement] of placements.entries()) {
12644
+ if (!placement.stubTracePath || placement.pinIds.length !== 1) continue;
12645
+ const direction = getStubDirection(placement.stubTracePath);
12646
+ if (!direction) continue;
12647
+ const ownerChipId = chipIdByPinId.get(placement.pinIds[0]);
12648
+ const groupKey = `${ownerChipId ?? placement.pinIds[0]}::${direction}`;
12649
+ const group = groups.get(groupKey) ?? [];
12650
+ group.push({ placementIndex, placement, direction, ownerChipId });
12651
+ groups.set(groupKey, group);
12652
+ }
12653
+ const alignedPlacements = [...placements];
12654
+ const supersededGlobalNetIds = new Set(
12655
+ placements.map((placement) => placement.globalConnNetId)
12656
+ );
12657
+ const retainedAnchoredLabelBounds = netLabelPlacements.filter(
12658
+ (placement) => !supersededGlobalNetIds.has(placement.globalConnNetId)
12659
+ ).map(getLabelBounds2);
12660
+ for (const group of groups.values()) {
12661
+ if (group.length < 2) continue;
12662
+ const targetLength = Math.max(
12663
+ ...group.map(({ placement }) => getStubLength(placement.stubTracePath))
12664
+ );
12665
+ const proposals = group.map(
12666
+ ({ placement, direction }) => resizeStub(placement, direction, targetLength)
12667
+ );
12668
+ const groupPlacementIndices = new Set(
12669
+ group.map(({ placementIndex }) => placementIndex)
12670
+ );
12671
+ const fixedInlinePlacements = placements.filter(
12672
+ (_, placementIndex) => !groupPlacementIndices.has(placementIndex)
12673
+ );
12674
+ const hasConflict = proposals.some((proposal, proposalIndex) => {
12675
+ const labelBounds = getLabelBounds2(proposal);
12676
+ const stubPath = proposal.stubTracePath;
12677
+ const stubBounds = getPathBounds(stubPath);
12678
+ const ownerChipId = group[proposalIndex].ownerChipId;
12679
+ for (const chip of inputProblem.chips) {
12680
+ const chipBounds = {
12681
+ minX: chip.center.x - chip.width / 2,
12682
+ maxX: chip.center.x + chip.width / 2,
12683
+ minY: chip.center.y - chip.height / 2,
12684
+ maxY: chip.center.y + chip.height / 2
12685
+ };
12686
+ if (boundsOverlap(labelBounds, chipBounds)) return true;
12687
+ if (chip.chipId !== ownerChipId && boundsOverlap(stubBounds, chipBounds))
12688
+ return true;
12689
+ }
12690
+ for (const textBox of inputProblem.textBoxes ?? []) {
12691
+ const textBounds = getTextBoxBounds(textBox);
12692
+ if (boundsOverlap(labelBounds, textBounds) || boundsOverlap(stubBounds, textBounds))
12693
+ return true;
12694
+ }
12695
+ for (const trace of traces) {
12696
+ if (trace.globalConnNetId === proposal.globalConnNetId) continue;
12697
+ if (doesPathIntersectBounds(trace.tracePath, labelBounds) || doesPathIntersectBounds(trace.tracePath, stubBounds))
12698
+ return true;
12699
+ }
12700
+ if (retainedAnchoredLabelBounds.some(
12701
+ (bounds) => boundsOverlap(labelBounds, bounds) || boundsOverlap(stubBounds, bounds)
12702
+ ))
12703
+ return true;
12704
+ for (const fixedPlacement of fixedInlinePlacements) {
12705
+ const fixedLabelBounds = getLabelBounds2(fixedPlacement);
12706
+ if (boundsOverlap(labelBounds, fixedLabelBounds) || boundsOverlap(stubBounds, fixedLabelBounds))
12707
+ return true;
12708
+ if (fixedPlacement.stubTracePath && (doesPathIntersectBounds(fixedPlacement.stubTracePath, labelBounds) || doesPathIntersectBounds(stubPath, fixedLabelBounds)))
12709
+ return true;
12710
+ }
12711
+ for (const [otherIndex, otherProposal] of proposals.entries()) {
12712
+ if (otherIndex === proposalIndex) continue;
12713
+ const otherLabelBounds = getLabelBounds2(otherProposal);
12714
+ if (boundsOverlap(labelBounds, otherLabelBounds)) return true;
12715
+ if (doesPathIntersectBounds(stubPath, otherLabelBounds)) return true;
12716
+ }
12717
+ return false;
12718
+ });
12719
+ if (hasConflict) continue;
12720
+ for (const [groupIndex, { placementIndex }] of group.entries()) {
12721
+ alignedPlacements[placementIndex] = proposals[groupIndex];
12722
+ }
12723
+ }
12724
+ return alignedPlacements;
12725
+ };
12726
+
12579
12727
  // lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts
12580
12728
  var DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
12581
12729
  var INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
@@ -12588,7 +12736,10 @@ var InlineNetLabelSolver = class extends BaseSolver {
12588
12736
  inlineNetLabelPlacements = [];
12589
12737
  /** Direct connections that opted in, still waiting to be processed */
12590
12738
  queuedDirectConnections;
12739
+ /** Single-pin net connections that opted in, still waiting to be processed */
12740
+ queuedPortOnlyNetConnections;
12591
12741
  tracesByPinPairKey;
12742
+ hasAlignedPortOnlyStubs = false;
12592
12743
  constructor(input) {
12593
12744
  super();
12594
12745
  this.inputProblem = input.inputProblem;
@@ -12597,6 +12748,9 @@ var InlineNetLabelSolver = class extends BaseSolver {
12597
12748
  this.queuedDirectConnections = this.inputProblem.directConnections.filter(
12598
12749
  (dc) => dc.allowInlineNetLabel && dc.netId
12599
12750
  );
12751
+ this.queuedPortOnlyNetConnections = this.inputProblem.netConnections.filter(
12752
+ (nc) => nc.allowInlineNetLabel && nc.pinIds.length === 1 && nc.netId
12753
+ );
12600
12754
  this.tracesByPinPairKey = /* @__PURE__ */ new Map();
12601
12755
  for (const trace of this.traces) {
12602
12756
  const key = getPinPairKey2(trace.pins.map((p) => p.pinId));
@@ -12619,15 +12773,97 @@ var InlineNetLabelSolver = class extends BaseSolver {
12619
12773
  }
12620
12774
  _step() {
12621
12775
  const directConnection = this.queuedDirectConnections.shift();
12622
- if (!directConnection) {
12623
- this.solved = true;
12624
- this.stats.inlineNetLabelCount = this.inlineNetLabelPlacements.length;
12776
+ if (directConnection) {
12777
+ const placement = this.computeInlinePlacement(directConnection);
12778
+ if (placement) {
12779
+ this.inlineNetLabelPlacements.push(placement);
12780
+ }
12781
+ return;
12782
+ }
12783
+ const portOnlyNetConnection = this.queuedPortOnlyNetConnections.shift();
12784
+ if (portOnlyNetConnection) {
12785
+ const placement = this.computePortOnlyInlinePlacement(
12786
+ portOnlyNetConnection
12787
+ );
12788
+ if (placement) {
12789
+ this.inlineNetLabelPlacements.push(placement);
12790
+ }
12625
12791
  return;
12626
12792
  }
12627
- const placement = this.computeInlinePlacement(directConnection);
12628
- if (placement) {
12629
- this.inlineNetLabelPlacements.push(placement);
12793
+ if (!this.hasAlignedPortOnlyStubs) {
12794
+ this.inlineNetLabelPlacements = alignPortOnlyInlineNetLabelStubs({
12795
+ placements: this.inlineNetLabelPlacements,
12796
+ inputProblem: this.inputProblem,
12797
+ traces: this.traces,
12798
+ netLabelPlacements: this.inputNetLabelPlacements
12799
+ });
12800
+ this.hasAlignedPortOnlyStubs = true;
12801
+ return;
12802
+ }
12803
+ this.solved = true;
12804
+ this.stats.inlineNetLabelCount = this.inlineNetLabelPlacements.length;
12805
+ }
12806
+ /**
12807
+ * Converts a conventional port-only anchored placement into an inline label
12808
+ * on a generated outward stub. The stub follows the pin's true facing
12809
+ * direction; an anchored label may finish in another direction after an
12810
+ * elbow, which is not the direction a terminal stub should leave the pin.
12811
+ */
12812
+ computePortOnlyInlinePlacement(netConnection) {
12813
+ const [pinId] = netConnection.pinIds;
12814
+ if (!pinId) return null;
12815
+ const anchoredPlacement = this.inputNetLabelPlacements.find(
12816
+ (placement) => placement.netId === netConnection.netId && placement.pinIds.length === 1 && placement.pinIds[0] === pinId
12817
+ );
12818
+ if (!anchoredPlacement) return null;
12819
+ const inputChip = this.inputProblem.chips.find(
12820
+ (chip) => chip.pins.some((pin) => pin.pinId === pinId)
12821
+ );
12822
+ const inputPin = inputChip?.pins.find((pin) => pin.pinId === pinId);
12823
+ const height = netConnection.inlineNetLabelHeight ?? DEFAULT_INLINE_NET_LABEL_HEIGHT;
12824
+ const width = netConnection.inlineNetLabelWidth ?? netConnection.netLabelWidth ?? estimateInlineNetLabelWidth(netConnection.netId, height);
12825
+ const stubLength = Math.max(width + 0.2, 0.6);
12826
+ const start = inputPin ? { x: inputPin.x, y: inputPin.y } : anchoredPlacement.anchorPoint;
12827
+ const direction = inputPin && inputChip ? inputPin._facingDirection ?? getPinDirection(inputPin, inputChip) : anchoredPlacement.orientation;
12828
+ const end = direction === "x+" ? { x: start.x + stubLength, y: start.y } : direction === "x-" ? { x: start.x - stubLength, y: start.y } : direction === "y+" ? { x: start.x, y: start.y + stubLength } : { x: start.x, y: start.y - stubLength };
12829
+ const axis = direction === "x+" || direction === "x-" ? "x" : "y";
12830
+ const side = axis === "x" ? "y+" : "x-";
12831
+ const anchorPoint = {
12832
+ x: (start.x + end.x) / 2,
12833
+ y: (start.y + end.y) / 2
12834
+ };
12835
+ const offset = height / 2 + INLINE_NET_LABEL_TRACE_MARGIN;
12836
+ const center = side === "y+" ? { x: anchorPoint.x, y: anchorPoint.y + offset } : { x: anchorPoint.x - offset, y: anchorPoint.y };
12837
+ const halfAlong = width / 2;
12838
+ const halfAcross = height / 2;
12839
+ const bounds = axis === "x" ? {
12840
+ minX: center.x - halfAlong,
12841
+ maxX: center.x + halfAlong,
12842
+ minY: center.y - halfAcross,
12843
+ maxY: center.y + halfAcross
12844
+ } : {
12845
+ minX: center.x - halfAcross,
12846
+ maxX: center.x + halfAcross,
12847
+ minY: center.y - halfAlong,
12848
+ maxY: center.y + halfAlong
12849
+ };
12850
+ if (this.isObstructed(bounds, {
12851
+ ownGlobalConnNetId: anchoredPlacement.globalConnNetId
12852
+ })) {
12853
+ return null;
12630
12854
  }
12855
+ return {
12856
+ globalConnNetId: anchoredPlacement.globalConnNetId,
12857
+ netId: netConnection.netId,
12858
+ pinIds: [pinId],
12859
+ stubTracePath: [start, end],
12860
+ axis,
12861
+ anchorPoint,
12862
+ center,
12863
+ width,
12864
+ height,
12865
+ side
12866
+ };
12631
12867
  }
12632
12868
  computeInlinePlacement(directConnection) {
12633
12869
  const traces = this.tracesByPinPairKey.get(getPinPairKey2(directConnection.pinIds)) ?? [];
@@ -12657,7 +12893,11 @@ var InlineNetLabelSolver = class extends BaseSolver {
12657
12893
  minY: center.y - halfAlong,
12658
12894
  maxY: center.y + halfAlong
12659
12895
  };
12660
- if (this.isObstructed(bounds, trace)) continue;
12896
+ if (this.isObstructed(bounds, {
12897
+ ownTrace: trace,
12898
+ ownGlobalConnNetId: trace.globalConnNetId
12899
+ }))
12900
+ continue;
12661
12901
  return {
12662
12902
  globalConnNetId: trace.globalConnNetId,
12663
12903
  netId: directConnection.netId,
@@ -12742,7 +12982,11 @@ var InlineNetLabelSolver = class extends BaseSolver {
12742
12982
  minY: center.y - halfAlong,
12743
12983
  maxY: center.y + halfAlong
12744
12984
  };
12745
- if (this.isObstructed(bounds, trace)) continue;
12985
+ if (this.isObstructed(bounds, {
12986
+ ownTrace: trace,
12987
+ ownGlobalConnNetId: trace.globalConnNetId
12988
+ }))
12989
+ continue;
12746
12990
  const anchorPoint = axis === "x" ? { x: along, y: side === "y+" ? maxY : minY } : { x: side === "x-" ? minX : maxX, y: along };
12747
12991
  return {
12748
12992
  globalConnNetId: trace.globalConnNetId,
@@ -12764,7 +13008,10 @@ var InlineNetLabelSolver = class extends BaseSolver {
12764
13008
  * An inline label may not sit on top of a chip, a component's text, or a
12765
13009
  * trace belonging to another net.
12766
13010
  */
12767
- isObstructed(bounds, ownTrace) {
13011
+ isObstructed(bounds, {
13012
+ ownTrace,
13013
+ ownGlobalConnNetId
13014
+ }) {
12768
13015
  for (const chip of this.inputProblem.chips) {
12769
13016
  const chipBounds = {
12770
13017
  minX: chip.center.x - chip.width / 2,
@@ -12778,9 +13025,9 @@ var InlineNetLabelSolver = class extends BaseSolver {
12778
13025
  if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true;
12779
13026
  }
12780
13027
  for (const trace of this.traces) {
12781
- if (trace.mspPairId === ownTrace.mspPairId) continue;
12782
- if (trace.globalConnNetId === ownTrace.globalConnNetId) continue;
12783
- if (doesPathIntersectBounds(trace.tracePath, bounds)) return true;
13028
+ if (ownTrace && trace.mspPairId === ownTrace.mspPairId) continue;
13029
+ if (trace.globalConnNetId === ownGlobalConnNetId) continue;
13030
+ if (doesPathIntersectBounds2(trace.tracePath, bounds)) return true;
12784
13031
  }
12785
13032
  return false;
12786
13033
  }
@@ -12795,10 +13042,18 @@ var InlineNetLabelSolver = class extends BaseSolver {
12795
13042
  }
12796
13043
  return keys;
12797
13044
  }
13045
+ getOutputTraces(supersededNetLabelKeys) {
13046
+ return this.traces.filter(
13047
+ (trace) => !(supersededNetLabelKeys.has(trace.globalConnNetId) && trace.mspPairId.startsWith("available-net-orientation-"))
13048
+ );
13049
+ }
12798
13050
  getOutput() {
12799
13051
  const superseded = this.getSupersededNetLabelKeys();
12800
13052
  return {
12801
- traces: this.traces,
13053
+ // AvailableNetOrientationSolver may have routed an elbow from a port to
13054
+ // the anchored label that this inline placement supersedes. Keep the
13055
+ // actual net trace, but discard that now-orphaned label connector.
13056
+ traces: this.getOutputTraces(superseded),
12802
13057
  netLabelPlacements: this.inputNetLabelPlacements.filter(
12803
13058
  (placement) => !superseded.has(placement.globalConnNetId)
12804
13059
  ),
@@ -12811,7 +13066,8 @@ var InlineNetLabelSolver = class extends BaseSolver {
12811
13066
  graphics.rects ??= [];
12812
13067
  graphics.points ??= [];
12813
13068
  graphics.texts ??= [];
12814
- for (const trace of this.traces) {
13069
+ const output = this.getOutput();
13070
+ for (const trace of output.traces) {
12815
13071
  graphics.lines.push({
12816
13072
  points: trace.tracePath,
12817
13073
  strokeColor: "purple"
@@ -12837,6 +13093,12 @@ orientation: ${label.orientation}`
12837
13093
  });
12838
13094
  }
12839
13095
  for (const inlineLabel of this.inlineNetLabelPlacements) {
13096
+ if (inlineLabel.stubTracePath) {
13097
+ graphics.lines.push({
13098
+ points: inlineLabel.stubTracePath,
13099
+ strokeColor: "purple"
13100
+ });
13101
+ }
12840
13102
  const isHorizontal4 = inlineLabel.axis === "x";
12841
13103
  graphics.rects.push({
12842
13104
  center: inlineLabel.center,
@@ -12851,12 +13113,12 @@ orientation: ${label.orientation}`
12851
13113
  ].join("\n")
12852
13114
  });
12853
13115
  graphics.texts.push({
12854
- x: inlineLabel.center.x,
12855
- y: inlineLabel.center.y,
13116
+ x: inlineLabel.stubTracePath && inlineLabel.axis === "x" ? inlineLabel.center.x + (inlineLabel.stubTracePath[1].x > inlineLabel.stubTracePath[0].x ? -inlineLabel.width / 2 : inlineLabel.width / 2) : inlineLabel.center.x,
13117
+ y: inlineLabel.stubTracePath && inlineLabel.axis === "y" ? inlineLabel.center.y + (inlineLabel.stubTracePath[1].y > inlineLabel.stubTracePath[0].y ? -inlineLabel.width / 2 : inlineLabel.width / 2) : inlineLabel.center.y,
12856
13118
  text: inlineLabel.netId ?? "",
12857
13119
  color: "green",
12858
13120
  fontSize: inlineLabel.height,
12859
- anchorSide: "center",
13121
+ anchorSide: inlineLabel.stubTracePath ? inlineLabel.stubTracePath[1][inlineLabel.axis] > inlineLabel.stubTracePath[0][inlineLabel.axis] ? "center_left" : "center_right" : "center",
12860
13122
  // Vertical labels read bottom-to-top, alongside the wire they name.
12861
13123
  rotation: inlineLabel.axis === "y" ? 90 : void 0
12862
13124
  });
@@ -12891,7 +13153,7 @@ var getAnchorCandidates = (segment, labelWidth, step = 0.1) => {
12891
13153
  offsets.push(slack / 2, -slack / 2);
12892
13154
  return offsets.map((offset) => pointAt(mid + offset * direction));
12893
13155
  };
12894
- var doesPathIntersectBounds = (path, bounds) => {
13156
+ var doesPathIntersectBounds2 = (path, bounds) => {
12895
13157
  for (let i = 0; i < path.length - 1; i++) {
12896
13158
  const a = path[i];
12897
13159
  const b = path[i + 1];