@tscircuit/schematic-trace-solver 0.0.69 → 0.0.70

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.js CHANGED
@@ -1234,12 +1234,43 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
1234
1234
  }) {
1235
1235
  const blockingCollisions = this.getBlockingCollisions({ group, offset });
1236
1236
  if (blockingCollisions.length === 0) return offset;
1237
- return blockingCollisions.flatMap(({ start, isVertical: isVertical4, obstacle }) => [
1238
- (isVertical4 ? obstacle.minX - start.x : obstacle.minY - start.y) - this.SHIFT_DISTANCE,
1239
- (isVertical4 ? obstacle.maxX - start.x : obstacle.maxY - start.y) + this.SHIFT_DISTANCE
1240
- ]).filter(
1241
- (candidateOffset) => this.getBlockingCollisions({ group, offset: candidateOffset }).length === 0
1242
- ).sort((a, b) => Math.abs(a - offset) - Math.abs(b - offset))[0] ?? offset;
1237
+ const crossesThroughObstacle = (candidateOffset) => blockingCollisions.some(({ start, isVertical: isVertical4, obstacle }) => {
1238
+ let orig;
1239
+ let min;
1240
+ let max;
1241
+ if (isVertical4) {
1242
+ orig = start.x;
1243
+ min = obstacle.minX;
1244
+ max = obstacle.maxX;
1245
+ } else {
1246
+ orig = start.y;
1247
+ min = obstacle.minY;
1248
+ max = obstacle.maxY;
1249
+ }
1250
+ const next = orig + candidateOffset;
1251
+ return orig <= min + EPS4 && next >= max - EPS4 || orig >= max - EPS4 && next <= min + EPS4;
1252
+ });
1253
+ const edges = blockingCollisions.map(({ start, isVertical: isVertical4, obstacle }) => {
1254
+ if (isVertical4) {
1255
+ return {
1256
+ coord: start.x,
1257
+ lowEdge: obstacle.minX,
1258
+ highEdge: obstacle.maxX
1259
+ };
1260
+ }
1261
+ return { coord: start.y, lowEdge: obstacle.minY, highEdge: obstacle.maxY };
1262
+ });
1263
+ const bestCandidate = (clearance) => {
1264
+ const candidates = edges.flatMap(({ coord, lowEdge, highEdge }) => [
1265
+ lowEdge - coord - clearance,
1266
+ highEdge - coord + clearance
1267
+ ]);
1268
+ return candidates.filter((candidateOffset) => !crossesThroughObstacle(candidateOffset)).filter(
1269
+ (candidateOffset) => this.getBlockingCollisions({ group, offset: candidateOffset }).length === 0
1270
+ ).sort((a, b) => Math.abs(a - offset) - Math.abs(b - offset))[0];
1271
+ };
1272
+ const EDGE_MARGIN = this.SHIFT_DISTANCE / 10;
1273
+ return bestCandidate(this.SHIFT_DISTANCE) ?? bestCandidate(EDGE_MARGIN) ?? offset;
1243
1274
  }
1244
1275
  getBlockingCollisions({
1245
1276
  group,
@@ -180,21 +180,56 @@ export class TraceOverlapIssueSolver extends BaseSolver {
180
180
  const blockingCollisions = this.getBlockingCollisions({ group, offset })
181
181
  if (blockingCollisions.length === 0) return offset
182
182
 
183
- return (
184
- blockingCollisions
185
- .flatMap(({ start, isVertical, obstacle }) => [
186
- (isVertical ? obstacle.minX - start.x : obstacle.minY - start.y) -
187
- this.SHIFT_DISTANCE,
188
- (isVertical ? obstacle.maxX - start.x : obstacle.maxY - start.y) +
189
- this.SHIFT_DISTANCE,
190
- ])
183
+ const crossesThroughObstacle = (candidateOffset: number) =>
184
+ blockingCollisions.some(({ start, isVertical, obstacle }) => {
185
+ let orig: number
186
+ let min: number
187
+ let max: number
188
+ if (isVertical) {
189
+ orig = start.x
190
+ min = obstacle.minX
191
+ max = obstacle.maxX
192
+ } else {
193
+ orig = start.y
194
+ min = obstacle.minY
195
+ max = obstacle.maxY
196
+ }
197
+ const next = orig + candidateOffset
198
+ return (
199
+ (orig <= min + EPS && next >= max - EPS) ||
200
+ (orig >= max - EPS && next <= min + EPS)
201
+ )
202
+ })
203
+
204
+ const edges = blockingCollisions.map(({ start, isVertical, obstacle }) => {
205
+ if (isVertical) {
206
+ return {
207
+ coord: start.x,
208
+ lowEdge: obstacle.minX,
209
+ highEdge: obstacle.maxX,
210
+ }
211
+ }
212
+ return { coord: start.y, lowEdge: obstacle.minY, highEdge: obstacle.maxY }
213
+ })
214
+
215
+ const bestCandidate = (clearance: number) => {
216
+ const candidates = edges.flatMap(({ coord, lowEdge, highEdge }) => [
217
+ lowEdge - coord - clearance,
218
+ highEdge - coord + clearance,
219
+ ])
220
+ return candidates
221
+ .filter((candidateOffset) => !crossesThroughObstacle(candidateOffset))
191
222
  .filter(
192
223
  (candidateOffset) =>
193
224
  this.getBlockingCollisions({ group, offset: candidateOffset })
194
225
  .length === 0,
195
226
  )
196
- .sort((a, b) => Math.abs(a - offset) - Math.abs(b - offset))[0] ??
197
- offset
227
+ .sort((a, b) => Math.abs(a - offset) - Math.abs(b - offset))[0]
228
+ }
229
+
230
+ const EDGE_MARGIN = this.SHIFT_DISTANCE / 10
231
+ return (
232
+ bestCandidate(this.SHIFT_DISTANCE) ?? bestCandidate(EDGE_MARGIN) ?? offset
198
233
  )
199
234
  }
200
235
 
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.69",
4
+ "version": "0.0.70",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "cosmos",
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/assets/example42.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,139 @@
1
+ {
2
+ "chips": [
3
+ {
4
+ "chipId": "schematic_component_16",
5
+ "center": {
6
+ "x": 0,
7
+ "y": 0
8
+ },
9
+ "width": 4.4,
10
+ "height": 2,
11
+ "pins": [
12
+ {
13
+ "pinId": "U3.1",
14
+ "x": 2.6,
15
+ "y": 0.8499999999999999
16
+ },
17
+ {
18
+ "pinId": "U3.2",
19
+ "x": 2.6,
20
+ "y": 0.6499999999999999
21
+ },
22
+ {
23
+ "pinId": "U3.3",
24
+ "x": 2.6,
25
+ "y": 0.44999999999999996
26
+ },
27
+ {
28
+ "pinId": "U3.4",
29
+ "x": 2.6,
30
+ "y": 0.10000000000000009
31
+ },
32
+ {
33
+ "pinId": "U3.5",
34
+ "x": 2.6,
35
+ "y": -0.09999999999999987
36
+ },
37
+ {
38
+ "pinId": "U3.6",
39
+ "x": 2.6,
40
+ "y": -0.44999999999999984
41
+ },
42
+ {
43
+ "pinId": "U3.7",
44
+ "x": 2.6,
45
+ "y": -0.6499999999999999
46
+ },
47
+ {
48
+ "pinId": "U3.8",
49
+ "x": 2.6,
50
+ "y": -0.8499999999999999
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ "chipId": "schematic_component_17",
56
+ "center": {
57
+ "x": 3.2,
58
+ "y": -1.4
59
+ },
60
+ "width": 1.1,
61
+ "height": 0.7789106999999986,
62
+ "pins": [
63
+ {
64
+ "pinId": "R8.1",
65
+ "x": 2.6500000000000004,
66
+ "y": -1.4
67
+ },
68
+ {
69
+ "pinId": "R8.2",
70
+ "x": 3.75,
71
+ "y": -1.4
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "chipId": "schematic_component_18",
77
+ "center": {
78
+ "x": 3.2,
79
+ "y": -2.4
80
+ },
81
+ "width": 1.1,
82
+ "height": 0.7789106999999986,
83
+ "pins": [
84
+ {
85
+ "pinId": "R9.1",
86
+ "x": 2.6500000000000004,
87
+ "y": -2.4
88
+ },
89
+ {
90
+ "pinId": "R9.2",
91
+ "x": 3.75,
92
+ "y": -2.4
93
+ }
94
+ ]
95
+ }
96
+ ],
97
+ "directConnections": [],
98
+ "netConnections": [
99
+ {
100
+ "netId": "GND",
101
+ "pinIds": ["U3.8", "R8.2", "R9.2"],
102
+ "netLabelWidth": 0.48
103
+ },
104
+ {
105
+ "netId": "D_MINUS",
106
+ "pinIds": ["U3.3"],
107
+ "netLabelWidth": 0.96
108
+ },
109
+ {
110
+ "netId": "D_PLUS",
111
+ "pinIds": ["U3.2"],
112
+ "netLabelWidth": 0.84
113
+ },
114
+ {
115
+ "netId": "VBUS",
116
+ "pinIds": ["U3.1"],
117
+ "netLabelWidth": 0.6
118
+ },
119
+ {
120
+ "netId": "CC1",
121
+ "pinIds": ["U3.4", "R8.1"],
122
+ "netLabelWidth": 0.48
123
+ },
124
+ {
125
+ "netId": "CC2",
126
+ "pinIds": ["U3.5", "R9.1"],
127
+ "netLabelWidth": 0.48
128
+ }
129
+ ],
130
+ "availableNetLabelOrientations": {
131
+ "D_MINUS": ["x-", "x+"],
132
+ "D_PLUS": ["x-", "x+"],
133
+ "GND": ["y-"],
134
+ "VBUS": ["y+"],
135
+ "CC1": ["x-", "x+"],
136
+ "CC2": ["x-", "x+"]
137
+ },
138
+ "maxMspPairDistance": 2.4
139
+ }
@@ -0,0 +1,195 @@
1
+ <svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="100%" height="100%" fill="white" />
3
+ <g>
4
+ <circle data-type="point" data-label="U3.1
5
+ x+" data-x="2.6" data-y="0.8499999999999999" cx="477.8947368421052" cy="194.5684210526316" r="3" fill="hsl(81, 100%, 50%, 0.8)" />
6
+ </g>
7
+ <g>
8
+ <circle data-type="point" data-label="U3.2
9
+ x+" data-x="2.6" data-y="0.6499999999999999" cx="477.8947368421052" cy="211.4105263157895" r="3" fill="hsl(82, 100%, 50%, 0.8)" />
10
+ </g>
11
+ <g>
12
+ <circle data-type="point" data-label="U3.3
13
+ x+" data-x="2.6" data-y="0.44999999999999996" cx="477.8947368421052" cy="228.2526315789474" r="3" fill="hsl(83, 100%, 50%, 0.8)" />
14
+ </g>
15
+ <g>
16
+ <circle data-type="point" data-label="U3.4
17
+ x+" data-x="2.6" data-y="0.10000000000000009" cx="477.8947368421052" cy="257.7263157894737" r="3" fill="hsl(84, 100%, 50%, 0.8)" />
18
+ </g>
19
+ <g>
20
+ <circle data-type="point" data-label="U3.5
21
+ x+" data-x="2.6" data-y="-0.09999999999999987" cx="477.8947368421052" cy="274.5684210526316" r="3" fill="hsl(85, 100%, 50%, 0.8)" />
22
+ </g>
23
+ <g>
24
+ <circle data-type="point" data-label="U3.6
25
+ x+" data-x="2.6" data-y="-0.44999999999999984" cx="477.8947368421052" cy="304.0421052631579" r="3" fill="hsl(86, 100%, 50%, 0.8)" />
26
+ </g>
27
+ <g>
28
+ <circle data-type="point" data-label="U3.7
29
+ x+" data-x="2.6" data-y="-0.6499999999999999" cx="477.8947368421052" cy="320.88421052631577" r="3" fill="hsl(87, 100%, 50%, 0.8)" />
30
+ </g>
31
+ <g>
32
+ <circle data-type="point" data-label="U3.8
33
+ x+" data-x="2.6" data-y="-0.8499999999999999" cx="477.8947368421052" cy="337.7263157894737" r="3" fill="hsl(88, 100%, 50%, 0.8)" />
34
+ </g>
35
+ <g>
36
+ <circle data-type="point" data-label="R8.1
37
+ x-" data-x="2.6500000000000004" data-y="-1.4" cx="482.1052631578947" cy="384.0421052631579" r="3" fill="hsl(113, 100%, 50%, 0.8)" />
38
+ </g>
39
+ <g>
40
+ <circle data-type="point" data-label="R8.2
41
+ x+" data-x="3.75" data-y="-1.4" cx="574.7368421052631" cy="384.0421052631579" r="3" fill="hsl(114, 100%, 50%, 0.8)" />
42
+ </g>
43
+ <g>
44
+ <circle data-type="point" data-label="R9.1
45
+ x-" data-x="2.6500000000000004" data-y="-2.4" cx="482.1052631578947" cy="468.25263157894733" r="3" fill="hsl(354, 100%, 50%, 0.8)" />
46
+ </g>
47
+ <g>
48
+ <circle data-type="point" data-label="R9.2
49
+ x+" data-x="3.75" data-y="-2.4" cx="574.7368421052631" cy="468.25263157894733" r="3" fill="hsl(355, 100%, 50%, 0.8)" />
50
+ </g>
51
+ <g>
52
+ <circle data-type="point" data-label="anchorPoint
53
+ orientation: y+" data-x="2.701" data-y="1.001" cx="486.4" cy="181.8526315789474" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
54
+ </g>
55
+ <g>
56
+ <circle data-type="point" data-label="anchorPoint
57
+ orientation: x+" data-x="2.6" data-y="0.6499999999999999" cx="477.8947368421052" cy="211.4105263157895" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
58
+ </g>
59
+ <g>
60
+ <circle data-type="point" data-label="anchorPoint
61
+ orientation: x+" data-x="2.6" data-y="0.44999999999999996" cx="477.8947368421052" cy="228.2526315789474" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
62
+ </g>
63
+ <g>
64
+ <circle data-type="point" data-label="anchorPoint
65
+ orientation: x+" data-x="2.61" data-y="0.10000000000000009" cx="478.7368421052631" cy="257.7263157894737" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
66
+ </g>
67
+ <g>
68
+ <circle data-type="point" data-label="anchorPoint
69
+ orientation: x+" data-x="2.6400000000000006" data-y="-0.09999999999999987" cx="481.2631578947369" cy="274.5684210526316" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
70
+ </g>
71
+ <g>
72
+ <circle data-type="point" data-label="anchorPoint
73
+ orientation: y-" data-x="3.95" data-y="-2.4" cx="591.578947368421" cy="468.25263157894733" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
74
+ </g>
75
+ <g>
76
+ <polyline data-points="2.6,-0.8499999999999999 3.75,-1.4" data-type="line" data-label="" points="477.8947368421052,337.7263157894737 574.7368421052631,384.0421052631579" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
77
+ </g>
78
+ <g>
79
+ <polyline data-points="2.6,-0.8499999999999999 3.75,-2.4" data-type="line" data-label="" points="477.8947368421052,337.7263157894737 574.7368421052631,468.25263157894733" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
80
+ </g>
81
+ <g>
82
+ <polyline data-points="3.75,-1.4 3.75,-2.4" data-type="line" data-label="" points="574.7368421052631,384.0421052631579 574.7368421052631,468.25263157894733" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
83
+ </g>
84
+ <g>
85
+ <polyline data-points="2.6,0.10000000000000009 2.6500000000000004,-1.4" data-type="line" data-label="" points="477.8947368421052,257.7263157894737 482.1052631578947,384.0421052631579" fill="none" stroke="hsl(273, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
86
+ </g>
87
+ <g>
88
+ <polyline data-points="2.6,-0.09999999999999987 2.6500000000000004,-2.4" data-type="line" data-label="" points="477.8947368421052,274.5684210526316 482.1052631578947,468.25263157894733" fill="none" stroke="hsl(274, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
89
+ </g>
90
+ <g>
91
+ <polyline data-points="3.75,-2.4 3.95,-2.4 3.95,-1.4 3.75,-1.4" data-type="line" data-label="" points="574.7368421052631,468.25263157894733 591.578947368421,468.25263157894733 591.578947368421,384.0421052631579 574.7368421052631,384.0421052631579" fill="none" stroke="purple" stroke-width="1" />
92
+ </g>
93
+ <g>
94
+ <polyline data-points="2.6,-0.8499999999999999 3.95,-0.8499999999999999 3.95,-1.4 3.75,-1.4" data-type="line" data-label="" points="477.8947368421052,337.7263157894737 591.578947368421,337.7263157894737 591.578947368421,384.0421052631579 574.7368421052631,384.0421052631579" fill="none" stroke="purple" stroke-width="1" />
95
+ </g>
96
+ <g>
97
+ <polyline data-points="2.6,0.10000000000000009 2.61,0.10000000000000009 2.61,-1.2 2.435,-1.2 2.435,-1.4 2.6500000000000004,-1.4" data-type="line" data-label="" points="477.8947368421052,257.7263157894737 478.7368421052631,257.7263157894737 478.7368421052631,367.2 463.99999999999994,367.2 463.99999999999994,384.0421052631579 482.1052631578947,384.0421052631579" fill="none" stroke="purple" stroke-width="1" />
98
+ </g>
99
+ <g>
100
+ <polyline data-points="2.6,-0.09999999999999987 2.6400000000000006,-0.09999999999999987 2.6400000000000006,-1.25 2.4650000000000007,-1.25 2.4650000000000007,-2.4 2.6500000000000004,-2.4" data-type="line" data-label="" points="477.8947368421052,274.5684210526316 481.2631578947369,274.5684210526316 481.2631578947369,371.41052631578947 466.5263157894737,371.41052631578947 466.5263157894737,468.25263157894733 482.1052631578947,468.25263157894733" fill="none" stroke="purple" stroke-width="1" />
101
+ </g>
102
+ <g>
103
+ <polyline data-points="2.6,0.8499999999999999 2.701,0.8499999999999999 2.701,1.001" data-type="line" data-label="" points="477.8947368421052,194.5684210526316 486.4,194.5684210526316 486.4,181.8526315789474" fill="none" stroke="purple" stroke-width="1" />
104
+ </g>
105
+ <g>
106
+ <rect data-type="rect" data-label="schematic_component_16" data-x="0" data-y="0" x="39.99999999999997" y="181.93684210526317" width="437.8947368421052" height="168.42105263157896" fill="hsl(320, 100%, 50%, 0.8)" stroke="black" stroke-width="0.011875000000000002" />
107
+ </g>
108
+ <g>
109
+ <rect data-type="rect" data-label="schematic_component_17" data-x="3.2" data-y="-1.4" x="482.1052631578947" y="351.24586526315795" width="92.63157894736844" height="65.59247999999991" fill="hsl(320, 100%, 50%, 0.8)" stroke="black" stroke-width="0.011875000000000002" />
110
+ </g>
111
+ <g>
112
+ <rect data-type="rect" data-label="schematic_component_18" data-x="3.2" data-y="-2.4" x="482.1052631578947" y="435.45639157894743" width="92.63157894736844" height="65.59247999999985" fill="hsl(320, 100%, 50%, 0.8)" stroke="black" stroke-width="0.011875000000000002" />
113
+ </g>
114
+ <g>
115
+ <rect data-type="rect" data-label="netId: VBUS
116
+ globalConnNetId: connectivity_net3" data-x="2.701" data-y="1.301" x="477.978947368421" y="131.3263157894737" width="16.84210526315792" height="50.5263157894737" fill="#ef444466" stroke="#ef4444" stroke-width="0.011875000000000002" />
117
+ </g>
118
+ <g>
119
+ <rect data-type="rect" data-label="netId: D_PLUS
120
+ globalConnNetId: connectivity_net2" data-x="3.021" data-y="0.6499999999999999" x="477.978947368421" y="202.98947368421057" width="70.73684210526312" height="16.84210526315789" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.011875000000000002" />
121
+ </g>
122
+ <g>
123
+ <rect data-type="rect" data-label="netId: D_MINUS
124
+ globalConnNetId: connectivity_net1" data-x="3.081" data-y="0.44999999999999996" x="477.978947368421" y="219.83157894736846" width="80.8421052631578" height="16.84210526315789" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.011875000000000002" />
125
+ </g>
126
+ <g>
127
+ <rect data-type="rect" data-label="netId: CC1
128
+ globalConnNetId: connectivity_net4" data-x="2.8499999999999996" data-y="0.10000000000000009" x="478.73684210526307" y="249.30526315789476" width="40.421052631579016" height="16.84210526315789" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.011875000000000002" />
129
+ </g>
130
+ <g>
131
+ <rect data-type="rect" data-label="netId: CC2
132
+ globalConnNetId: connectivity_net5" data-x="2.880000000000001" data-y="-0.09999999999999987" x="481.2631578947369" y="266.14736842105265" width="40.42105263157896" height="16.842105263157862" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.011875000000000002" />
133
+ </g>
134
+ <g>
135
+ <rect data-type="rect" data-label="netId: GND
136
+ globalConnNetId: connectivity_net0" data-x="3.95" data-y="-2.6399999999999997" x="583.1578947368421" y="468.25263157894733" width="16.84210526315792" height="40.42105263157896" fill="#00000066" stroke="#000000" stroke-width="0.011875000000000002" />
137
+ </g>
138
+ <g id="crosshair" style="display: none">
139
+ <line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
140
+ <line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5" /><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text>
141
+ </g>
142
+ <script>
143
+ <![CDATA[
144
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
145
+ const svg = e.currentTarget;
146
+ const rect = svg.getBoundingClientRect();
147
+ const x = e.clientX - rect.left;
148
+ const y = e.clientY - rect.top;
149
+ const crosshair = svg.getElementById('crosshair');
150
+ const h = svg.getElementById('crosshair-h');
151
+ const v = svg.getElementById('crosshair-v');
152
+ const coords = svg.getElementById('coordinates');
153
+
154
+ crosshair.style.display = 'block';
155
+ h.setAttribute('x1', '0');
156
+ h.setAttribute('x2', '640');
157
+ h.setAttribute('y1', y);
158
+ h.setAttribute('y2', y);
159
+ v.setAttribute('x1', x);
160
+ v.setAttribute('x2', x);
161
+ v.setAttribute('y1', '0');
162
+ v.setAttribute('y2', '640');
163
+
164
+ // Calculate real coordinates using inverse transformation
165
+ const matrix = {
166
+ "a": 84.21052631578947,
167
+ "c": 0,
168
+ "e": 258.9473684210526,
169
+ "b": 0,
170
+ "d": -84.21052631578947,
171
+ "f": 266.14736842105265
172
+ };
173
+ // Manually invert and apply the affine transform
174
+ // Since we only use translate and scale, we can directly compute:
175
+ // x' = (x - tx) / sx
176
+ // y' = (y - ty) / sy
177
+ const sx = matrix.a;
178
+ const sy = matrix.d;
179
+ const tx = matrix.e;
180
+ const ty = matrix.f;
181
+ const realPoint = {
182
+ x: (x - tx) / sx,
183
+ y: (y - ty) / sy // Flip y back since we used negative scale
184
+ }
185
+
186
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
187
+ coords.setAttribute('x', (x + 5).toString());
188
+ coords.setAttribute('y', (y - 5).toString());
189
+ });
190
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
191
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
192
+ });
193
+ ]]>
194
+ </script>
195
+ </svg>
@@ -0,0 +1,12 @@
1
+ import { test, expect } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import inputProblem from "../assets/example42.json"
4
+ import "tests/fixtures/matcher"
5
+
6
+ test("example42", () => {
7
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
8
+
9
+ solver.solve()
10
+
11
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
12
+ })