@tscircuit/schematic-trace-solver 0.0.38 → 0.0.39

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
@@ -392,14 +392,13 @@ declare class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
392
392
  private netTempLabelPlacements;
393
393
  private netLabelPlacements;
394
394
  private updatedTraces;
395
- private updatedTracesMap;
396
395
  private mergedLabelNetIdMap;
397
396
  private detourCountByLabel;
398
397
  private readonly PADDING_BUFFER;
399
398
  constructor(solverInput: TraceLabelOverlapAvoidanceSolverInput);
400
399
  _step(): void;
401
400
  getOutput(): {
402
- traceMap: Map<string, SolvedTracePath>;
401
+ traces: SolvedTracePath[];
403
402
  netLabelPlacements: NetLabelPlacement[];
404
403
  };
405
404
  visualize(): GraphicsObject;
package/dist/index.js CHANGED
@@ -1015,12 +1015,12 @@ var applyJogToTerminalSegment = ({
1015
1015
  if (si !== 0 && si !== pts.length - 2) return;
1016
1016
  const start = pts[si];
1017
1017
  const end = pts[si + 1];
1018
- const isVertical3 = Math.abs(start.x - end.x) < EPS4;
1019
- const isHorizontal3 = Math.abs(start.y - end.y) < EPS4;
1020
- if (!isVertical3 && !isHorizontal3) return;
1021
- const segDir = isVertical3 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
1018
+ const isVertical2 = Math.abs(start.x - end.x) < EPS4;
1019
+ const isHorizontal2 = Math.abs(start.y - end.y) < EPS4;
1020
+ if (!isVertical2 && !isHorizontal2) return;
1021
+ const segDir = isVertical2 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
1022
1022
  if (si === 0) {
1023
- if (isVertical3) {
1023
+ if (isVertical2) {
1024
1024
  const jogY = start.y + segDir * JOG_SIZE;
1025
1025
  pts.splice(
1026
1026
  1,
@@ -1040,7 +1040,7 @@ var applyJogToTerminalSegment = ({
1040
1040
  );
1041
1041
  }
1042
1042
  } else {
1043
- if (isVertical3) {
1043
+ if (isVertical2) {
1044
1044
  const jogY = end.y - segDir * JOG_SIZE;
1045
1045
  pts.splice(
1046
1046
  si,
@@ -1120,10 +1120,10 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
1120
1120
  } else {
1121
1121
  const start = pts[si];
1122
1122
  const end = pts[si + 1];
1123
- const isVertical3 = Math.abs(start.x - end.x) < EPS4;
1124
- const isHorizontal3 = Math.abs(start.y - end.y) < EPS4;
1125
- if (!isVertical3 && !isHorizontal3) continue;
1126
- if (isVertical3) {
1123
+ const isVertical2 = Math.abs(start.x - end.x) < EPS4;
1124
+ const isHorizontal2 = Math.abs(start.y - end.y) < EPS4;
1125
+ if (!isVertical2 && !isHorizontal2) continue;
1126
+ if (isVertical2) {
1127
1127
  start.x += offset;
1128
1128
  end.x += offset;
1129
1129
  } else {
@@ -2508,6 +2508,32 @@ var countTurns = (points) => {
2508
2508
  return turns;
2509
2509
  };
2510
2510
 
2511
+ // lib/solvers/TraceLabelOverlapAvoidanceSolver/tryConnectPoints.ts
2512
+ var tryConnectPoints = (start, end) => {
2513
+ const candidates = [];
2514
+ if (start.x === end.x || start.y === end.y) {
2515
+ candidates.push([start, end]);
2516
+ } else {
2517
+ candidates.push([start, { x: end.x, y: start.y }, end]);
2518
+ candidates.push([start, { x: start.x, y: end.y }, end]);
2519
+ }
2520
+ return candidates;
2521
+ };
2522
+
2523
+ // lib/solvers/TraceLabelOverlapAvoidanceSolver/hasCollisionsWithLabels.ts
2524
+ var hasCollisionsWithLabels = (pathSegments, labels) => {
2525
+ for (let i = 0; i < pathSegments.length - 1; i++) {
2526
+ const p1 = pathSegments[i];
2527
+ const p2 = pathSegments[i + 1];
2528
+ for (const label of labels) {
2529
+ if (segmentIntersectsRect(p1, p2, label)) {
2530
+ return true;
2531
+ }
2532
+ }
2533
+ }
2534
+ return false;
2535
+ };
2536
+
2511
2537
  // lib/solvers/TraceLabelOverlapAvoidanceSolver/turnMinimization.ts
2512
2538
  var minimizeTurns = ({
2513
2539
  path,
@@ -2517,28 +2543,6 @@ var minimizeTurns = ({
2517
2543
  if (path.length <= 2) {
2518
2544
  return path;
2519
2545
  }
2520
- const hasCollisionsWithLabels = (pathSegments, labels) => {
2521
- for (let i = 0; i < pathSegments.length - 1; i++) {
2522
- const p1 = pathSegments[i];
2523
- const p2 = pathSegments[i + 1];
2524
- for (const label of labels) {
2525
- if (segmentIntersectsRect(p1, p2, label)) {
2526
- return true;
2527
- }
2528
- }
2529
- }
2530
- return false;
2531
- };
2532
- const tryConnectPoints = (start, end) => {
2533
- const candidates = [];
2534
- if (start.x === end.x || start.y === end.y) {
2535
- candidates.push([start, end]);
2536
- } else {
2537
- candidates.push([start, { x: end.x, y: start.y }, end]);
2538
- candidates.push([start, { x: start.x, y: end.y }, end]);
2539
- }
2540
- return candidates;
2541
- };
2542
2546
  const recognizeStairStepPattern = (pathToCheck, startIdx) => {
2543
2547
  if (startIdx >= pathToCheck.length - 3) return -1;
2544
2548
  let endIdx = startIdx;
@@ -2672,6 +2676,8 @@ var minimizeTurns = ({
2672
2676
  const finalSimplifiedPath = simplifyPath(optimizedPath);
2673
2677
  return finalSimplifiedPath;
2674
2678
  };
2679
+
2680
+ // lib/solvers/TraceLabelOverlapAvoidanceSolver/minimizeTurnsWithFilteredLabels.ts
2675
2681
  var minimizeTurnsWithFilteredLabels = ({
2676
2682
  traces,
2677
2683
  problem,
@@ -2684,7 +2690,7 @@ var minimizeTurnsWithFilteredLabels = ({
2684
2690
  const newTraces = traces.map((trace) => {
2685
2691
  const originalPath = trace.tracePath;
2686
2692
  const filteredLabels = allLabelPlacements.filter((label) => {
2687
- const originalNetIds = mergedLabelNetIdMap.get(label.globalConnNetId);
2693
+ const originalNetIds = mergedLabelNetIdMap[label.globalConnNetId];
2688
2694
  if (originalNetIds) {
2689
2695
  return !originalNetIds.has(trace.globalConnNetId);
2690
2696
  }
@@ -2865,7 +2871,6 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2865
2871
  netTempLabelPlacements;
2866
2872
  netLabelPlacements;
2867
2873
  updatedTraces;
2868
- updatedTracesMap;
2869
2874
  mergedLabelNetIdMap;
2870
2875
  detourCountByLabel;
2871
2876
  PADDING_BUFFER = 0.1;
@@ -2874,28 +2879,27 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2874
2879
  this.problem = solverInput.inputProblem;
2875
2880
  this.traces = solverInput.traces;
2876
2881
  this.updatedTraces = [...solverInput.traces];
2877
- this.updatedTracesMap = /* @__PURE__ */ new Map();
2878
- this.mergedLabelNetIdMap = /* @__PURE__ */ new Map();
2879
- this.detourCountByLabel = /* @__PURE__ */ new Map();
2882
+ this.mergedLabelNetIdMap = {};
2883
+ this.detourCountByLabel = {};
2880
2884
  const originalLabels = solverInput.netLabelPlacements;
2881
2885
  this.netLabelPlacements = originalLabels;
2882
2886
  if (!originalLabels || originalLabels.length === 0) {
2883
2887
  this.netTempLabelPlacements = [];
2884
2888
  return;
2885
2889
  }
2886
- const labelGroups = /* @__PURE__ */ new Map();
2890
+ const labelGroups = {};
2887
2891
  for (const p of originalLabels) {
2888
2892
  if (p.pinIds.length === 0) continue;
2889
2893
  const chipId = p.pinIds[0].split(".")[0];
2890
2894
  if (!chipId) continue;
2891
2895
  const key = `${chipId}-${p.orientation}`;
2892
- if (!labelGroups.has(key)) {
2893
- labelGroups.set(key, []);
2896
+ if (!(key in labelGroups)) {
2897
+ labelGroups[key] = [];
2894
2898
  }
2895
- labelGroups.get(key).push(p);
2899
+ labelGroups[key].push(p);
2896
2900
  }
2897
2901
  const finalPlacements = [];
2898
- for (const [key, group] of labelGroups.entries()) {
2902
+ for (const [key, group] of Object.entries(labelGroups)) {
2899
2903
  if (group.length <= 1) {
2900
2904
  finalPlacements.push(...group);
2901
2905
  continue;
@@ -2913,7 +2917,7 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2913
2917
  const template = group[0];
2914
2918
  const syntheticId = `merged-group-${key}`;
2915
2919
  const originalNetIds = new Set(group.map((p) => p.globalConnNetId));
2916
- this.mergedLabelNetIdMap.set(syntheticId, originalNetIds);
2920
+ this.mergedLabelNetIdMap[syntheticId] = originalNetIds;
2917
2921
  finalPlacements.push({
2918
2922
  ...template,
2919
2923
  globalConnNetId: syntheticId,
@@ -2933,7 +2937,7 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2933
2937
  this.solved = true;
2934
2938
  return;
2935
2939
  }
2936
- this.detourCountByLabel.clear();
2940
+ this.detourCountByLabel = {};
2937
2941
  const overlaps = detectTraceLabelOverlap(
2938
2942
  this.traces,
2939
2943
  this.netTempLabelPlacements
@@ -2943,9 +2947,7 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2943
2947
  return;
2944
2948
  }
2945
2949
  const unfriendlyOverlaps = overlaps.filter((o) => {
2946
- const originalNetIds = this.mergedLabelNetIdMap.get(
2947
- o.label.globalConnNetId
2948
- );
2950
+ const originalNetIds = this.mergedLabelNetIdMap[o.label.globalConnNetId];
2949
2951
  if (originalNetIds) {
2950
2952
  return !originalNetIds.has(o.trace.globalConnNetId);
2951
2953
  }
@@ -2955,18 +2957,18 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2955
2957
  this.solved = true;
2956
2958
  return;
2957
2959
  }
2958
- const updatedTracesMap = /* @__PURE__ */ new Map();
2960
+ const updatedTracesMap = {};
2959
2961
  for (const trace of this.traces) {
2960
- updatedTracesMap.set(trace.mspPairId, trace);
2962
+ updatedTracesMap[trace.mspPairId] = trace;
2961
2963
  }
2962
2964
  const processedTraceIds = /* @__PURE__ */ new Set();
2963
2965
  for (const overlap of unfriendlyOverlaps) {
2964
2966
  if (processedTraceIds.has(overlap.trace.mspPairId)) {
2965
2967
  continue;
2966
2968
  }
2967
- const currentTraceState = updatedTracesMap.get(overlap.trace.mspPairId);
2969
+ const currentTraceState = updatedTracesMap[overlap.trace.mspPairId];
2968
2970
  const labelId = overlap.label.globalConnNetId;
2969
- const detourCount = this.detourCountByLabel.get(labelId) || 0;
2971
+ const detourCount = this.detourCountByLabel[labelId] || 0;
2970
2972
  const newTrace = rerouteCollidingTrace({
2971
2973
  trace: currentTraceState,
2972
2974
  label: overlap.label,
@@ -2975,12 +2977,12 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
2975
2977
  detourCount
2976
2978
  });
2977
2979
  if (newTrace.tracePath !== currentTraceState.tracePath) {
2978
- this.detourCountByLabel.set(labelId, detourCount + 1);
2980
+ this.detourCountByLabel[labelId] = detourCount + 1;
2979
2981
  }
2980
- updatedTracesMap.set(currentTraceState.mspPairId, newTrace);
2982
+ updatedTracesMap[currentTraceState.mspPairId] = newTrace;
2981
2983
  processedTraceIds.add(currentTraceState.mspPairId);
2982
2984
  }
2983
- this.updatedTraces = Array.from(updatedTracesMap.values());
2985
+ this.updatedTraces = Object.values(updatedTracesMap);
2984
2986
  const minimizedTraces = minimizeTurnsWithFilteredLabels({
2985
2987
  traces: this.updatedTraces,
2986
2988
  problem: this.problem,
@@ -3000,13 +3002,11 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
3000
3002
  if (balancedTraces) {
3001
3003
  this.updatedTraces = balancedTraces;
3002
3004
  }
3003
- this.updatedTracesMap.clear();
3004
- for (const trace of this.updatedTraces) {
3005
- this.updatedTracesMap.set(trace.mspPairId, trace);
3006
- }
3007
3005
  const finalLabelPlacementSolver = new NetLabelPlacementSolver({
3008
3006
  inputProblem: this.problem,
3009
- inputTraceMap: Object.fromEntries(this.updatedTracesMap)
3007
+ inputTraceMap: Object.fromEntries(
3008
+ this.updatedTraces.map((trace) => [trace.mspPairId, trace])
3009
+ )
3010
3010
  });
3011
3011
  finalLabelPlacementSolver.solve();
3012
3012
  this.netLabelPlacements = finalLabelPlacementSolver.netLabelPlacements;
@@ -3014,7 +3014,7 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
3014
3014
  }
3015
3015
  getOutput() {
3016
3016
  return {
3017
- traceMap: this.updatedTracesMap,
3017
+ traces: this.updatedTraces,
3018
3018
  netLabelPlacements: this.netLabelPlacements
3019
3019
  };
3020
3020
  }
@@ -3024,7 +3024,7 @@ var TraceLabelOverlapAvoidanceSolver = class extends BaseSolver {
3024
3024
  if (!graphics.circles) graphics.circles = [];
3025
3025
  if (!graphics.texts) graphics.texts = [];
3026
3026
  if (!graphics.rects) graphics.rects = [];
3027
- for (const trace of Object.values(this.updatedTraces)) {
3027
+ for (const trace of this.updatedTraces) {
3028
3028
  graphics.lines.push({
3029
3029
  points: trace.tracePath,
3030
3030
  strokeColor: "purple"
@@ -8,7 +8,7 @@ import { visualizeInputProblem } from "../SchematicTracePipelineSolver/visualize
8
8
  import { getRectBounds } from "../NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry"
9
9
  import { getColorFromString } from "lib/utils/getColorFromString"
10
10
  import type { InputProblem } from "lib/types/InputProblem"
11
- import { minimizeTurnsWithFilteredLabels } from "./turnMinimization"
11
+ import { minimizeTurnsWithFilteredLabels } from "./minimizeTurnsWithFilteredLabels"
12
12
  import { balanceLShapes } from "./balanceLShapes"
13
13
  import { NetLabelPlacementSolver } from "../NetLabelPlacementSolver/NetLabelPlacementSolver"
14
14
 
@@ -24,9 +24,8 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
24
24
  private netTempLabelPlacements: NetLabelPlacement[]
25
25
  private netLabelPlacements: NetLabelPlacement[]
26
26
  private updatedTraces: SolvedTracePath[]
27
- private updatedTracesMap: Map<string, SolvedTracePath>
28
- private mergedLabelNetIdMap: Map<string, Set<string>>
29
- private detourCountByLabel: Map<string, number>
27
+ private mergedLabelNetIdMap: Record<string, Set<string>>
28
+ private detourCountByLabel: Record<string, number>
30
29
  private readonly PADDING_BUFFER = 0.1
31
30
 
32
31
  constructor(solverInput: TraceLabelOverlapAvoidanceSolverInput) {
@@ -34,9 +33,8 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
34
33
  this.problem = solverInput.inputProblem
35
34
  this.traces = solverInput.traces
36
35
  this.updatedTraces = [...solverInput.traces]
37
- this.updatedTracesMap = new Map()
38
- this.mergedLabelNetIdMap = new Map()
39
- this.detourCountByLabel = new Map()
36
+ this.mergedLabelNetIdMap = {}
37
+ this.detourCountByLabel = {}
40
38
 
41
39
  const originalLabels = solverInput.netLabelPlacements
42
40
  this.netLabelPlacements = originalLabels
@@ -45,21 +43,21 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
45
43
  return
46
44
  }
47
45
 
48
- const labelGroups = new Map<string, NetLabelPlacement[]>()
46
+ const labelGroups: Record<string, NetLabelPlacement[]> = {}
49
47
 
50
48
  for (const p of originalLabels) {
51
49
  if (p.pinIds.length === 0) continue
52
50
  const chipId = p.pinIds[0].split(".")[0]
53
51
  if (!chipId) continue
54
52
  const key = `${chipId}-${p.orientation}`
55
- if (!labelGroups.has(key)) {
56
- labelGroups.set(key, [])
53
+ if (!(key in labelGroups)) {
54
+ labelGroups[key] = []
57
55
  }
58
- labelGroups.get(key)!.push(p)
56
+ labelGroups[key]!.push(p)
59
57
  }
60
58
 
61
59
  const finalPlacements: NetLabelPlacement[] = []
62
- for (const [key, group] of labelGroups.entries()) {
60
+ for (const [key, group] of Object.entries(labelGroups)) {
63
61
  if (group.length <= 1) {
64
62
  finalPlacements.push(...group)
65
63
  continue
@@ -82,7 +80,7 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
82
80
  const template = group[0]!
83
81
  const syntheticId = `merged-group-${key}`
84
82
  const originalNetIds = new Set(group.map((p) => p.globalConnNetId))
85
- this.mergedLabelNetIdMap.set(syntheticId, originalNetIds)
83
+ this.mergedLabelNetIdMap[syntheticId] = originalNetIds
86
84
 
87
85
  finalPlacements.push({
88
86
  ...template,
@@ -111,7 +109,7 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
111
109
  return
112
110
  }
113
111
 
114
- this.detourCountByLabel.clear()
112
+ this.detourCountByLabel = {}
115
113
 
116
114
  const overlaps = detectTraceLabelOverlap(
117
115
  this.traces,
@@ -124,9 +122,7 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
124
122
  }
125
123
 
126
124
  const unfriendlyOverlaps = overlaps.filter((o) => {
127
- const originalNetIds = this.mergedLabelNetIdMap.get(
128
- o.label.globalConnNetId,
129
- )
125
+ const originalNetIds = this.mergedLabelNetIdMap[o.label.globalConnNetId]
130
126
  if (originalNetIds) {
131
127
  return !originalNetIds.has(o.trace.globalConnNetId)
132
128
  }
@@ -138,9 +134,9 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
138
134
  return
139
135
  }
140
136
 
141
- const updatedTracesMap = new Map<string, SolvedTracePath>()
137
+ const updatedTracesMap: Record<string, SolvedTracePath> = {}
142
138
  for (const trace of this.traces) {
143
- updatedTracesMap.set(trace.mspPairId, trace)
139
+ updatedTracesMap[trace.mspPairId] = trace
144
140
  }
145
141
 
146
142
  const processedTraceIds = new Set<string>()
@@ -150,9 +146,9 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
150
146
  continue
151
147
  }
152
148
 
153
- const currentTraceState = updatedTracesMap.get(overlap.trace.mspPairId)!
149
+ const currentTraceState = updatedTracesMap[overlap.trace.mspPairId]!
154
150
  const labelId = overlap.label.globalConnNetId
155
- const detourCount = this.detourCountByLabel.get(labelId) || 0
151
+ const detourCount = this.detourCountByLabel[labelId] || 0
156
152
 
157
153
  const newTrace = rerouteCollidingTrace({
158
154
  trace: currentTraceState,
@@ -163,14 +159,14 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
163
159
  })
164
160
 
165
161
  if (newTrace.tracePath !== currentTraceState.tracePath) {
166
- this.detourCountByLabel.set(labelId, detourCount + 1)
162
+ this.detourCountByLabel[labelId] = detourCount + 1
167
163
  }
168
164
 
169
- updatedTracesMap.set(currentTraceState.mspPairId, newTrace)
165
+ updatedTracesMap[currentTraceState.mspPairId] = newTrace
170
166
  processedTraceIds.add(currentTraceState.mspPairId)
171
167
  }
172
168
 
173
- this.updatedTraces = Array.from(updatedTracesMap.values())
169
+ this.updatedTraces = Object.values(updatedTracesMap)
174
170
 
175
171
  const minimizedTraces = minimizeTurnsWithFilteredLabels({
176
172
  traces: this.updatedTraces,
@@ -191,14 +187,11 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
191
187
  this.updatedTraces = balancedTraces
192
188
  }
193
189
 
194
- this.updatedTracesMap.clear()
195
- for (const trace of this.updatedTraces) {
196
- this.updatedTracesMap.set(trace.mspPairId, trace)
197
- }
198
-
199
190
  const finalLabelPlacementSolver = new NetLabelPlacementSolver({
200
191
  inputProblem: this.problem,
201
- inputTraceMap: Object.fromEntries(this.updatedTracesMap),
192
+ inputTraceMap: Object.fromEntries(
193
+ this.updatedTraces.map((trace) => [trace.mspPairId, trace]),
194
+ ),
202
195
  })
203
196
  finalLabelPlacementSolver.solve()
204
197
  this.netLabelPlacements = finalLabelPlacementSolver.netLabelPlacements
@@ -208,7 +201,7 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
208
201
 
209
202
  getOutput() {
210
203
  return {
211
- traceMap: this.updatedTracesMap,
204
+ traces: this.updatedTraces,
212
205
  netLabelPlacements: this.netLabelPlacements,
213
206
  }
214
207
  }
@@ -221,7 +214,7 @@ export class TraceLabelOverlapAvoidanceSolver extends BaseSolver {
221
214
  if (!graphics.texts) graphics.texts = []
222
215
  if (!graphics.rects) graphics.rects = []
223
216
 
224
- for (const trace of Object.values(this.updatedTraces)) {
217
+ for (const trace of this.updatedTraces) {
225
218
  graphics.lines!.push({
226
219
  points: trace.tracePath,
227
220
  strokeColor: "purple",
@@ -1,9 +1,5 @@
1
1
  import type { Point } from "graphics-debug"
2
- import {
3
- isVertical,
4
- isHorizontal,
5
- segmentIntersectsRect,
6
- } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
2
+ import { segmentIntersectsRect } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
7
3
 
8
4
  export const hasCollisions = (
9
5
  pathSegments: Point[],
@@ -0,0 +1,19 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import { segmentIntersectsRect } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
3
+
4
+ export const hasCollisionsWithLabels = (
5
+ pathSegments: Point[],
6
+ labels: any[],
7
+ ): boolean => {
8
+ for (let i = 0; i < pathSegments.length - 1; i++) {
9
+ const p1 = pathSegments[i]
10
+ const p2 = pathSegments[i + 1]
11
+
12
+ for (const label of labels) {
13
+ if (segmentIntersectsRect(p1, p2, label)) {
14
+ return true
15
+ }
16
+ }
17
+ }
18
+ return false
19
+ }
@@ -0,0 +1,66 @@
1
+ import type { InputProblem } from "lib/types/InputProblem"
2
+ import type { NetLabelPlacement } from "../NetLabelPlacementSolver/NetLabelPlacementSolver"
3
+ import type { SolvedTracePath } from "../SchematicTraceLinesSolver/SchematicTraceLinesSolver"
4
+ import { getObstacleRects } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect"
5
+ import { minimizeTurns } from "./turnMinimization"
6
+
7
+ export const minimizeTurnsWithFilteredLabels = ({
8
+ traces,
9
+ problem,
10
+ allLabelPlacements,
11
+ mergedLabelNetIdMap,
12
+ paddingBuffer,
13
+ }: {
14
+ traces: SolvedTracePath[]
15
+ problem: InputProblem
16
+ allLabelPlacements: NetLabelPlacement[]
17
+ mergedLabelNetIdMap: Record<string, Set<string>>
18
+ paddingBuffer: number
19
+ }): SolvedTracePath[] | null => {
20
+ let changesMade = false
21
+ const obstacles = getObstacleRects(problem)
22
+
23
+ const newTraces = traces.map((trace) => {
24
+ const originalPath = trace.tracePath
25
+ const filteredLabels = allLabelPlacements.filter((label) => {
26
+ const originalNetIds = mergedLabelNetIdMap[label.globalConnNetId]
27
+ if (originalNetIds) {
28
+ return !originalNetIds.has(trace.globalConnNetId)
29
+ }
30
+ return label.globalConnNetId !== trace.globalConnNetId
31
+ })
32
+
33
+ const labelBounds = filteredLabels.map((nl) => ({
34
+ minX: nl.center.x - nl.width / 2 - paddingBuffer,
35
+ maxX: nl.center.x + nl.width / 2 + paddingBuffer,
36
+ minY: nl.center.y - nl.height / 2 - paddingBuffer,
37
+ maxY: nl.center.y + nl.height / 2 + paddingBuffer,
38
+ }))
39
+
40
+ const newPath = minimizeTurns({
41
+ path: originalPath,
42
+ obstacles,
43
+ labelBounds,
44
+ })
45
+
46
+ if (
47
+ newPath.length !== originalPath.length ||
48
+ newPath.some(
49
+ (p, i) => p.x !== originalPath[i].x || p.y !== originalPath[i].y,
50
+ )
51
+ ) {
52
+ changesMade = true
53
+ }
54
+
55
+ return {
56
+ ...trace,
57
+ tracePath: newPath,
58
+ }
59
+ })
60
+
61
+ if (changesMade) {
62
+ return newTraces
63
+ } else {
64
+ return null
65
+ }
66
+ }
@@ -0,0 +1,14 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+
3
+ export const tryConnectPoints = (start: Point, end: Point): Point[][] => {
4
+ const candidates: Point[][] = []
5
+
6
+ if (start.x === end.x || start.y === end.y) {
7
+ candidates.push([start, end])
8
+ } else {
9
+ candidates.push([start, { x: end.x, y: start.y }, end])
10
+ candidates.push([start, { x: start.x, y: end.y }, end])
11
+ }
12
+
13
+ return candidates
14
+ }
@@ -1,14 +1,11 @@
1
1
  import type { Point } from "graphics-debug"
2
- import type { InputProblem } from "lib/types/InputProblem"
3
- import type { NetLabelPlacement } from "../NetLabelPlacementSolver/NetLabelPlacementSolver"
4
- import { getObstacleRects } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect"
5
- import type { SolvedTracePath } from "../SchematicTraceLinesSolver/SchematicTraceLinesSolver"
6
- import { segmentIntersectsRect } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
7
2
  import { hasCollisions } from "./hasCollisions"
8
3
  import { countTurns } from "./countTurns"
9
4
  import { simplifyPath } from "./simplifyPath"
5
+ import { tryConnectPoints } from "./tryConnectPoints"
6
+ import { hasCollisionsWithLabels } from "./hasCollisionsWithLabels"
10
7
 
11
- const minimizeTurns = ({
8
+ export const minimizeTurns = ({
12
9
  path,
13
10
  obstacles,
14
11
  labelBounds,
@@ -21,36 +18,6 @@ const minimizeTurns = ({
21
18
  return path
22
19
  }
23
20
 
24
- const hasCollisionsWithLabels = (
25
- pathSegments: Point[],
26
- labels: any[],
27
- ): boolean => {
28
- for (let i = 0; i < pathSegments.length - 1; i++) {
29
- const p1 = pathSegments[i]
30
- const p2 = pathSegments[i + 1]
31
-
32
- for (const label of labels) {
33
- if (segmentIntersectsRect(p1, p2, label)) {
34
- return true
35
- }
36
- }
37
- }
38
- return false
39
- }
40
-
41
- const tryConnectPoints = (start: Point, end: Point): Point[][] => {
42
- const candidates: Point[][] = []
43
-
44
- if (start.x === end.x || start.y === end.y) {
45
- candidates.push([start, end])
46
- } else {
47
- candidates.push([start, { x: end.x, y: start.y }, end])
48
- candidates.push([start, { x: start.x, y: end.y }, end])
49
- }
50
-
51
- return candidates
52
- }
53
-
54
21
  const recognizeStairStepPattern = (
55
22
  pathToCheck: Point[],
56
23
  startIdx: number,
@@ -242,64 +209,3 @@ const minimizeTurns = ({
242
209
  const finalSimplifiedPath = simplifyPath(optimizedPath)
243
210
  return finalSimplifiedPath
244
211
  }
245
-
246
- export const minimizeTurnsWithFilteredLabels = ({
247
- traces,
248
- problem,
249
- allLabelPlacements,
250
- mergedLabelNetIdMap,
251
- paddingBuffer,
252
- }: {
253
- traces: SolvedTracePath[]
254
- problem: InputProblem
255
- allLabelPlacements: NetLabelPlacement[]
256
- mergedLabelNetIdMap: Map<string, Set<string>>
257
- paddingBuffer: number
258
- }): SolvedTracePath[] | null => {
259
- let changesMade = false
260
- const obstacles = getObstacleRects(problem)
261
-
262
- const newTraces = traces.map((trace) => {
263
- const originalPath = trace.tracePath
264
- const filteredLabels = allLabelPlacements.filter((label) => {
265
- const originalNetIds = mergedLabelNetIdMap.get(label.globalConnNetId)
266
- if (originalNetIds) {
267
- return !originalNetIds.has(trace.globalConnNetId)
268
- }
269
- return label.globalConnNetId !== trace.globalConnNetId
270
- })
271
-
272
- const labelBounds = filteredLabels.map((nl) => ({
273
- minX: nl.center.x - nl.width / 2 - paddingBuffer,
274
- maxX: nl.center.x + nl.width / 2 + paddingBuffer,
275
- minY: nl.center.y - nl.height / 2 - paddingBuffer,
276
- maxY: nl.center.y + nl.height / 2 + paddingBuffer,
277
- }))
278
-
279
- const newPath = minimizeTurns({
280
- path: originalPath,
281
- obstacles,
282
- labelBounds,
283
- })
284
-
285
- if (
286
- newPath.length !== originalPath.length ||
287
- newPath.some(
288
- (p, i) => p.x !== originalPath[i].x || p.y !== originalPath[i].y,
289
- )
290
- ) {
291
- changesMade = true
292
- }
293
-
294
- return {
295
- ...trace,
296
- tracePath: newPath,
297
- }
298
- })
299
-
300
- if (changesMade) {
301
- return newTraces
302
- } else {
303
- return null
304
- }
305
- }
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.38",
4
+ "version": "0.0.39",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "cosmos",