@tscircuit/schematic-trace-solver 0.0.136 → 0.0.137

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
@@ -1117,6 +1117,7 @@ interface SameNetJunctionAlignmentSolverInput {
1117
1117
  declare class SameNetJunctionAlignmentSolver extends BaseSolver {
1118
1118
  private input;
1119
1119
  outputTraces: SolvedTracePath[];
1120
+ outputNetLabelPlacements: NetLabelPlacement[];
1120
1121
  constructor(input: SameNetJunctionAlignmentSolverInput);
1121
1122
  _step(): void;
1122
1123
  getOutput(): {
package/dist/index.js CHANGED
@@ -11749,6 +11749,35 @@ var railIsOnFacingSide = ({
11749
11749
  if (pin._facingDirection === "y+") return railY > pin.y;
11750
11750
  return false;
11751
11751
  };
11752
+ var getAttachedLabelIndexes = (trace, netLabelPlacements) => netLabelPlacements.flatMap((label, index) => {
11753
+ const labelOwnsTrace = label.mspConnectionPairIds.includes(trace.mspPairId) || label.mspConnectionPairIds.length === 0 && label.globalConnNetId === trace.globalConnNetId;
11754
+ return labelOwnsTrace && tracePathContainsPoint(trace.tracePath, label.anchorPoint) ? [index] : [];
11755
+ });
11756
+ var moveAttachedLabels = ({
11757
+ trace,
11758
+ reroutedTracePath,
11759
+ netLabelPlacements,
11760
+ attachedLabelIndexes
11761
+ }) => {
11762
+ const attachedLabels = attachedLabelIndexes.map(
11763
+ (index) => netLabelPlacements[index]
11764
+ );
11765
+ const movedAttachedLabels = moveAttachedLabelsToReroutedTrace({
11766
+ trace,
11767
+ originalTracePath: trace.tracePath,
11768
+ reroutedTracePath,
11769
+ netLabelPlacements: attachedLabels
11770
+ });
11771
+ const movedLabelByIndex = new Map(
11772
+ attachedLabelIndexes.map((labelIndex, index) => [
11773
+ labelIndex,
11774
+ movedAttachedLabels[index]
11775
+ ])
11776
+ );
11777
+ return netLabelPlacements.map(
11778
+ (label, index) => movedLabelByIndex.get(index) ?? label
11779
+ );
11780
+ };
11752
11781
  var getAlignedBranchPath = ({
11753
11782
  donorTrace,
11754
11783
  branchTrace
@@ -11789,7 +11818,8 @@ var candidateIsClear = ({
11789
11818
  originalTrace,
11790
11819
  traces,
11791
11820
  inputProblem,
11792
- netLabelPlacements
11821
+ candidateNetLabelPlacements,
11822
+ attachedLabelIndexes
11793
11823
  }) => {
11794
11824
  const obstacles = getObstacleRects(inputProblem);
11795
11825
  if (isPathCollidingWithObstacles(candidateTrace.tracePath, obstacles)) {
@@ -11801,14 +11831,15 @@ var candidateIsClear = ({
11801
11831
  if (doesPathCoincideWithTraces(candidateTrace.tracePath, otherNetTraces)) {
11802
11832
  return false;
11803
11833
  }
11804
- const candidateTraces = traces.map((trace) => {
11805
- if (trace.mspPairId === originalTrace.mspPairId) return candidateTrace;
11806
- return trace;
11807
- });
11808
- if (!preservesLabelAnchors(netLabelPlacements, traces, candidateTraces)) {
11834
+ if (!attachedLabelIndexes.every(
11835
+ (index) => tracePathContainsPoint(
11836
+ candidateTrace.tracePath,
11837
+ candidateNetLabelPlacements[index].anchorPoint
11838
+ )
11839
+ )) {
11809
11840
  return false;
11810
11841
  }
11811
- const otherNetLabelPlacements = netLabelPlacements.filter(
11842
+ const otherNetLabelPlacements = candidateNetLabelPlacements.filter(
11812
11843
  (label) => label.globalConnNetId !== candidateTrace.globalConnNetId
11813
11844
  );
11814
11845
  if (pathIntersectsAnyNetLabel({
@@ -11817,7 +11848,7 @@ var candidateIsClear = ({
11817
11848
  })) {
11818
11849
  return false;
11819
11850
  }
11820
- const sameNetLabelPlacements = netLabelPlacements.filter(
11851
+ const sameNetLabelPlacements = candidateNetLabelPlacements.filter(
11821
11852
  (label) => label.globalConnNetId === candidateTrace.globalConnNetId
11822
11853
  );
11823
11854
  if (!pathIntersectsAnyNetLabel({
@@ -11843,9 +11874,14 @@ var alignSameNetJunctions = ({
11843
11874
  netLabelPlacements
11844
11875
  }) => {
11845
11876
  let outputTraces = [...traces];
11877
+ let outputNetLabelPlacements = [...netLabelPlacements];
11846
11878
  const alignedBranchTraceIds = /* @__PURE__ */ new Set();
11847
11879
  let alignedJunctionCount = 0;
11848
- for (const donorTraceId of traces.map((trace) => trace.mspPairId)) {
11880
+ const donorTraceIds = traces.map((trace) => trace.mspPairId);
11881
+ const pendingDonorTraceIds = new Set(donorTraceIds);
11882
+ for (let donorIndex = 0; donorIndex < donorTraceIds.length; donorIndex++) {
11883
+ const donorTraceId = donorTraceIds[donorIndex];
11884
+ pendingDonorTraceIds.delete(donorTraceId);
11849
11885
  const donorTrace = outputTraces.find(
11850
11886
  (trace) => trace.mspPairId === donorTraceId
11851
11887
  );
@@ -11866,12 +11902,23 @@ var alignSameNetJunctions = ({
11866
11902
  if (!removesVisibleSegment && !shortensVisibleTrace) {
11867
11903
  continue;
11868
11904
  }
11905
+ const attachedLabelIndexes = getAttachedLabelIndexes(
11906
+ branchTrace,
11907
+ outputNetLabelPlacements
11908
+ );
11909
+ const candidateNetLabelPlacements = moveAttachedLabels({
11910
+ trace: branchTrace,
11911
+ reroutedTracePath: candidatePath,
11912
+ netLabelPlacements: outputNetLabelPlacements,
11913
+ attachedLabelIndexes
11914
+ });
11869
11915
  if (!candidateIsClear({
11870
11916
  candidateTrace,
11871
11917
  originalTrace: branchTrace,
11872
11918
  traces: outputTraces,
11873
11919
  inputProblem,
11874
- netLabelPlacements
11920
+ candidateNetLabelPlacements,
11921
+ attachedLabelIndexes
11875
11922
  })) {
11876
11923
  continue;
11877
11924
  }
@@ -11879,32 +11926,44 @@ var alignSameNetJunctions = ({
11879
11926
  if (trace.mspPairId === branchTrace.mspPairId) return candidateTrace;
11880
11927
  return trace;
11881
11928
  });
11929
+ outputNetLabelPlacements = candidateNetLabelPlacements;
11882
11930
  alignedBranchTraceIds.add(branchTrace.mspPairId);
11883
11931
  alignedJunctionCount++;
11932
+ if (!pendingDonorTraceIds.has(branchTrace.mspPairId)) {
11933
+ donorTraceIds.push(branchTrace.mspPairId);
11934
+ pendingDonorTraceIds.add(branchTrace.mspPairId);
11935
+ }
11884
11936
  }
11885
11937
  }
11886
- return { traces: outputTraces, alignedJunctionCount };
11938
+ return {
11939
+ traces: outputTraces,
11940
+ netLabelPlacements: outputNetLabelPlacements,
11941
+ alignedJunctionCount
11942
+ };
11887
11943
  };
11888
11944
 
11889
11945
  // lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts
11890
11946
  var SameNetJunctionAlignmentSolver = class extends BaseSolver {
11891
11947
  input;
11892
11948
  outputTraces;
11949
+ outputNetLabelPlacements;
11893
11950
  constructor(input) {
11894
11951
  super();
11895
11952
  this.input = input;
11896
11953
  this.outputTraces = input.traces;
11954
+ this.outputNetLabelPlacements = input.netLabelPlacements;
11897
11955
  }
11898
11956
  _step() {
11899
11957
  const result = alignSameNetJunctions(this.input);
11900
11958
  this.outputTraces = result.traces;
11959
+ this.outputNetLabelPlacements = result.netLabelPlacements;
11901
11960
  this.stats.alignedJunctionCount = result.alignedJunctionCount;
11902
11961
  this.solved = true;
11903
11962
  }
11904
11963
  getOutput() {
11905
11964
  return {
11906
11965
  traces: this.outputTraces,
11907
- netLabelPlacements: this.input.netLabelPlacements
11966
+ netLabelPlacements: this.outputNetLabelPlacements
11908
11967
  };
11909
11968
  }
11910
11969
  visualize() {
@@ -11918,7 +11977,7 @@ var SameNetJunctionAlignmentSolver = class extends BaseSolver {
11918
11977
  strokeColor: "purple"
11919
11978
  });
11920
11979
  }
11921
- for (const label of this.input.netLabelPlacements) {
11980
+ for (const label of this.outputNetLabelPlacements) {
11922
11981
  const labelRect = {
11923
11982
  center: label.center,
11924
11983
  width: label.width,
@@ -17,16 +17,19 @@ interface SameNetJunctionAlignmentSolverInput {
17
17
  export class SameNetJunctionAlignmentSolver extends BaseSolver {
18
18
  private input: SameNetJunctionAlignmentSolverInput
19
19
  outputTraces: SolvedTracePath[]
20
+ outputNetLabelPlacements: NetLabelPlacement[]
20
21
 
21
22
  constructor(input: SameNetJunctionAlignmentSolverInput) {
22
23
  super()
23
24
  this.input = input
24
25
  this.outputTraces = input.traces
26
+ this.outputNetLabelPlacements = input.netLabelPlacements
25
27
  }
26
28
 
27
29
  override _step() {
28
30
  const result = alignSameNetJunctions(this.input)
29
31
  this.outputTraces = result.traces
32
+ this.outputNetLabelPlacements = result.netLabelPlacements
30
33
  this.stats.alignedJunctionCount = result.alignedJunctionCount
31
34
  this.solved = true
32
35
  }
@@ -34,7 +37,7 @@ export class SameNetJunctionAlignmentSolver extends BaseSolver {
34
37
  getOutput() {
35
38
  return {
36
39
  traces: this.outputTraces,
37
- netLabelPlacements: this.input.netLabelPlacements,
40
+ netLabelPlacements: this.outputNetLabelPlacements,
38
41
  }
39
42
  }
40
43
 
@@ -49,7 +52,7 @@ export class SameNetJunctionAlignmentSolver extends BaseSolver {
49
52
  strokeColor: "purple",
50
53
  })
51
54
  }
52
- for (const label of this.input.netLabelPlacements) {
55
+ for (const label of this.outputNetLabelPlacements) {
53
56
  const labelRect: Rect & { strokeColor: string } = {
54
57
  center: label.center,
55
58
  width: label.width,
@@ -3,8 +3,9 @@ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetL
3
3
  import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
4
4
  import { isPathCollidingWithObstacles } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
5
5
  import { getObstacleRects } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect"
6
+ import { moveAttachedLabelsToReroutedTrace } from "lib/solvers/Example28Solver/labelMovement"
7
+ import { tracePathContainsPoint } from "lib/solvers/RailNetLabelCornerPlacementSolver/geometry"
6
8
  import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
7
- import { preservesLabelAnchors } from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors"
8
9
  import {
9
10
  getVisibleTraceLength,
10
11
  getVisibleTraceSegmentCount,
@@ -95,6 +96,52 @@ const railIsOnFacingSide = ({
95
96
  return false
96
97
  }
97
98
 
99
+ const getAttachedLabelIndexes = (
100
+ trace: SolvedTracePath,
101
+ netLabelPlacements: NetLabelPlacement[],
102
+ ) =>
103
+ netLabelPlacements.flatMap((label, index) => {
104
+ const labelOwnsTrace =
105
+ label.mspConnectionPairIds.includes(trace.mspPairId) ||
106
+ (label.mspConnectionPairIds.length === 0 &&
107
+ label.globalConnNetId === trace.globalConnNetId)
108
+ return labelOwnsTrace &&
109
+ tracePathContainsPoint(trace.tracePath, label.anchorPoint)
110
+ ? [index]
111
+ : []
112
+ })
113
+
114
+ const moveAttachedLabels = ({
115
+ trace,
116
+ reroutedTracePath,
117
+ netLabelPlacements,
118
+ attachedLabelIndexes,
119
+ }: {
120
+ trace: SolvedTracePath
121
+ reroutedTracePath: Point[]
122
+ netLabelPlacements: NetLabelPlacement[]
123
+ attachedLabelIndexes: number[]
124
+ }) => {
125
+ const attachedLabels = attachedLabelIndexes.map(
126
+ (index) => netLabelPlacements[index]!,
127
+ )
128
+ const movedAttachedLabels = moveAttachedLabelsToReroutedTrace({
129
+ trace,
130
+ originalTracePath: trace.tracePath,
131
+ reroutedTracePath,
132
+ netLabelPlacements: attachedLabels,
133
+ })
134
+ const movedLabelByIndex = new Map(
135
+ attachedLabelIndexes.map((labelIndex, index) => [
136
+ labelIndex,
137
+ movedAttachedLabels[index]!,
138
+ ]),
139
+ )
140
+ return netLabelPlacements.map(
141
+ (label, index) => movedLabelByIndex.get(index) ?? label,
142
+ )
143
+ }
144
+
98
145
  const getAlignedBranchPath = ({
99
146
  donorTrace,
100
147
  branchTrace,
@@ -145,13 +192,15 @@ const candidateIsClear = ({
145
192
  originalTrace,
146
193
  traces,
147
194
  inputProblem,
148
- netLabelPlacements,
195
+ candidateNetLabelPlacements,
196
+ attachedLabelIndexes,
149
197
  }: {
150
198
  candidateTrace: SolvedTracePath
151
199
  originalTrace: SolvedTracePath
152
200
  traces: SolvedTracePath[]
153
201
  inputProblem: InputProblem
154
- netLabelPlacements: NetLabelPlacement[]
202
+ candidateNetLabelPlacements: NetLabelPlacement[]
203
+ attachedLabelIndexes: number[]
155
204
  }) => {
156
205
  const obstacles = getObstacleRects(inputProblem)
157
206
  if (isPathCollidingWithObstacles(candidateTrace.tracePath, obstacles)) {
@@ -165,15 +214,18 @@ const candidateIsClear = ({
165
214
  return false
166
215
  }
167
216
 
168
- const candidateTraces = traces.map((trace) => {
169
- if (trace.mspPairId === originalTrace.mspPairId) return candidateTrace
170
- return trace
171
- })
172
- if (!preservesLabelAnchors(netLabelPlacements, traces, candidateTraces)) {
217
+ if (
218
+ !attachedLabelIndexes.every((index) =>
219
+ tracePathContainsPoint(
220
+ candidateTrace.tracePath,
221
+ candidateNetLabelPlacements[index]!.anchorPoint,
222
+ ),
223
+ )
224
+ ) {
173
225
  return false
174
226
  }
175
227
 
176
- const otherNetLabelPlacements = netLabelPlacements.filter(
228
+ const otherNetLabelPlacements = candidateNetLabelPlacements.filter(
177
229
  (label) => label.globalConnNetId !== candidateTrace.globalConnNetId,
178
230
  )
179
231
  if (
@@ -185,7 +237,7 @@ const candidateIsClear = ({
185
237
  return false
186
238
  }
187
239
 
188
- const sameNetLabelPlacements = netLabelPlacements.filter(
240
+ const sameNetLabelPlacements = candidateNetLabelPlacements.filter(
189
241
  (label) => label.globalConnNetId === candidateTrace.globalConnNetId,
190
242
  )
191
243
  // A same-net rail may follow its label edge, but never enter the label body.
@@ -221,11 +273,18 @@ export const alignSameNetJunctions = ({
221
273
  netLabelPlacements,
222
274
  }: AlignSameNetJunctionsInput) => {
223
275
  let outputTraces = [...traces]
276
+ let outputNetLabelPlacements = [...netLabelPlacements]
224
277
  const alignedBranchTraceIds = new Set<string>()
225
278
  let alignedJunctionCount = 0
226
279
 
227
- // Reuse each aligned branch as the rail for the next load in the chain.
228
- for (const donorTraceId of traces.map((trace) => trace.mspPairId)) {
280
+ // Reuse each aligned branch as the rail for the next load in the chain. An
281
+ // aligned branch may already have had its donor turn, so queue it again when
282
+ // its geometry changes.
283
+ const donorTraceIds = traces.map((trace) => trace.mspPairId)
284
+ const pendingDonorTraceIds = new Set(donorTraceIds)
285
+ for (let donorIndex = 0; donorIndex < donorTraceIds.length; donorIndex++) {
286
+ const donorTraceId = donorTraceIds[donorIndex]!
287
+ pendingDonorTraceIds.delete(donorTraceId)
229
288
  const donorTrace = outputTraces.find(
230
289
  (trace) => trace.mspPairId === donorTraceId,
231
290
  )!
@@ -252,13 +311,24 @@ export const alignSameNetJunctions = ({
252
311
  if (!removesVisibleSegment && !shortensVisibleTrace) {
253
312
  continue
254
313
  }
314
+ const attachedLabelIndexes = getAttachedLabelIndexes(
315
+ branchTrace,
316
+ outputNetLabelPlacements,
317
+ )
318
+ const candidateNetLabelPlacements = moveAttachedLabels({
319
+ trace: branchTrace,
320
+ reroutedTracePath: candidatePath,
321
+ netLabelPlacements: outputNetLabelPlacements,
322
+ attachedLabelIndexes,
323
+ })
255
324
  if (
256
325
  !candidateIsClear({
257
326
  candidateTrace,
258
327
  originalTrace: branchTrace,
259
328
  traces: outputTraces,
260
329
  inputProblem,
261
- netLabelPlacements,
330
+ candidateNetLabelPlacements,
331
+ attachedLabelIndexes,
262
332
  })
263
333
  ) {
264
334
  continue
@@ -268,10 +338,19 @@ export const alignSameNetJunctions = ({
268
338
  if (trace.mspPairId === branchTrace.mspPairId) return candidateTrace
269
339
  return trace
270
340
  })
341
+ outputNetLabelPlacements = candidateNetLabelPlacements
271
342
  alignedBranchTraceIds.add(branchTrace.mspPairId)
272
343
  alignedJunctionCount++
344
+ if (!pendingDonorTraceIds.has(branchTrace.mspPairId)) {
345
+ donorTraceIds.push(branchTrace.mspPairId)
346
+ pendingDonorTraceIds.add(branchTrace.mspPairId)
347
+ }
273
348
  }
274
349
  }
275
350
 
276
- return { traces: outputTraces, alignedJunctionCount }
351
+ return {
352
+ traces: outputTraces,
353
+ netLabelPlacements: outputNetLabelPlacements,
354
+ alignedJunctionCount,
355
+ }
277
356
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/schematic-trace-solver",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.136",
4
+ "version": "0.0.137",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "cosmos",