@tscircuit/schematic-trace-solver 0.0.84 → 0.0.86

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
@@ -5213,6 +5213,19 @@ var dir = (facingDirection) => {
5213
5213
  // lib/solvers/Example28Solver/types.ts
5214
5214
  var EPS7 = 1e-9;
5215
5215
 
5216
+ // lib/solvers/Example28Solver/segmentRunsAlongRectBoundary.ts
5217
+ var segmentRunsAlongRectBoundary = (start, end, rect) => {
5218
+ const isVertical4 = Math.abs(start.x - end.x) < EPS7;
5219
+ const isHorizontal3 = Math.abs(start.y - end.y) < EPS7;
5220
+ if (isVertical4) {
5221
+ return Math.abs(start.x - rect.minX) < EPS7 || Math.abs(start.x - rect.maxX) < EPS7;
5222
+ }
5223
+ if (isHorizontal3) {
5224
+ return Math.abs(start.y - rect.minY) < EPS7 || Math.abs(start.y - rect.maxY) < EPS7;
5225
+ }
5226
+ return false;
5227
+ };
5228
+
5216
5229
  // lib/solvers/Example28Solver/geometry.ts
5217
5230
  var getPathKey = (path) => path.map((point) => `${point.x},${point.y}`).join(";");
5218
5231
  var getPathLength = (path) => {
@@ -5350,17 +5363,6 @@ var isPathCollidingWithChipInterior = (path, chipObstacles) => {
5350
5363
  }
5351
5364
  return false;
5352
5365
  };
5353
- var segmentRunsAlongRectBoundary = (start, end, rect) => {
5354
- const isVertical4 = Math.abs(start.x - end.x) < EPS7;
5355
- const isHorizontal3 = Math.abs(start.y - end.y) < EPS7;
5356
- if (isVertical4) {
5357
- return Math.abs(start.x - rect.minX) < EPS7 || Math.abs(start.x - rect.maxX) < EPS7;
5358
- }
5359
- if (isHorizontal3) {
5360
- return Math.abs(start.y - rect.minY) < EPS7 || Math.abs(start.y - rect.maxY) < EPS7;
5361
- }
5362
- return false;
5363
- };
5364
5366
 
5365
5367
  // lib/solvers/Example28Solver/getMovedAnchorPointForReroute.ts
5366
5368
  var getMovedAnchorPointForReroute = (anchorPoint, originalTracePath, reroutedTracePath) => {
@@ -11,7 +11,12 @@ import {
11
11
  detectTraceLabelOverlap,
12
12
  type TraceLabelOverlap,
13
13
  } from "lib/solvers/TraceLabelOverlapAvoidanceSolver/detectTraceLabelOverlap"
14
- import type { InputPin, InputProblem } from "lib/types/InputProblem"
14
+ import type {
15
+ ChipId,
16
+ InputPin,
17
+ InputProblem,
18
+ PinId,
19
+ } from "lib/types/InputProblem"
15
20
  import { dir } from "lib/utils/dir"
16
21
  import { moveAttachedLabelsToReroutedTrace } from "./labelMovement"
17
22
  import { findBestReroutePath } from "./reroute"
@@ -34,7 +39,7 @@ export class Example28Solver extends BaseSolver {
34
39
  currentCandidateResults: RerouteCandidateResult[] = []
35
40
 
36
41
  private chipObstacles: ReturnType<typeof getObstacleRects>
37
- private pinMap: Record<string, InputPin & { chipId: string }>
42
+ private pinMap: Record<PinId, InputPin & { chipId: ChipId }>
38
43
 
39
44
  constructor(params: Example28SolverParams) {
40
45
  super()
@@ -277,7 +282,7 @@ const createPortOnlyLabelConnectorTrace = ({
277
282
  }: {
278
283
  label: NetLabelPlacement
279
284
  movedLabel: NetLabelPlacement
280
- pinMap: Record<string, InputPin & { chipId: string }>
285
+ pinMap: Record<PinId, InputPin & { chipId: ChipId }>
281
286
  }): SolvedTracePath => {
282
287
  const mspPairId = getPortOnlyLabelConnectorMspPairId(label)
283
288
 
@@ -0,0 +1,41 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import { segmentRunsAlongRectBoundary } from "./segmentRunsAlongRectBoundary"
3
+ import type { ChipObstacle } from "./types"
4
+ import { EPS } from "./types"
5
+
6
+ export const doesPathRunAlongChipBoundary = (
7
+ path: Point[],
8
+ chipObstacles: ChipObstacle[],
9
+ ) => {
10
+ for (let i = 0; i < path.length - 1; i++) {
11
+ const start = path[i]!
12
+ const end = path[i + 1]!
13
+ for (const obstacle of chipObstacles) {
14
+ if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue
15
+ if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS) {
16
+ return true
17
+ }
18
+ }
19
+ }
20
+ return false
21
+ }
22
+
23
+ const getSegmentOverlapWithRectSpan = (
24
+ start: Point,
25
+ end: Point,
26
+ rect: ChipObstacle,
27
+ ) => {
28
+ const isVertical = Math.abs(start.x - end.x) < EPS
29
+
30
+ if (isVertical) {
31
+ return (
32
+ Math.min(Math.max(start.y, end.y), rect.maxY) -
33
+ Math.max(Math.min(start.y, end.y), rect.minY)
34
+ )
35
+ }
36
+
37
+ return (
38
+ Math.min(Math.max(start.x, end.x), rect.maxX) -
39
+ Math.max(Math.min(start.x, end.x), rect.minX)
40
+ )
41
+ }
@@ -1,5 +1,6 @@
1
1
  import type { Point } from "@tscircuit/math-utils"
2
2
  import { segmentIntersectsRect } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
3
+ import { segmentRunsAlongRectBoundary } from "./segmentRunsAlongRectBoundary"
3
4
  import type { ChipObstacle, PathSegment, SegmentOrientation } from "./types"
4
5
  import { EPS } from "./types"
5
6
 
@@ -221,26 +222,3 @@ export const isPathCollidingWithChipInterior = (
221
222
  }
222
223
  return false
223
224
  }
224
-
225
- const segmentRunsAlongRectBoundary = (
226
- start: Point,
227
- end: Point,
228
- rect: ChipObstacle,
229
- ) => {
230
- const isVertical = Math.abs(start.x - end.x) < EPS
231
- const isHorizontal = Math.abs(start.y - end.y) < EPS
232
-
233
- if (isVertical) {
234
- return (
235
- Math.abs(start.x - rect.minX) < EPS || Math.abs(start.x - rect.maxX) < EPS
236
- )
237
- }
238
-
239
- if (isHorizontal) {
240
- return (
241
- Math.abs(start.y - rect.minY) < EPS || Math.abs(start.y - rect.maxY) < EPS
242
- )
243
- }
244
-
245
- return false
246
- }
@@ -0,0 +1,26 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import type { ChipObstacle } from "./types"
3
+ import { EPS } from "./types"
4
+
5
+ export const segmentRunsAlongRectBoundary = (
6
+ start: Point,
7
+ end: Point,
8
+ rect: ChipObstacle,
9
+ ) => {
10
+ const isVertical = Math.abs(start.x - end.x) < EPS
11
+ const isHorizontal = Math.abs(start.y - end.y) < EPS
12
+
13
+ if (isVertical) {
14
+ return (
15
+ Math.abs(start.x - rect.minX) < EPS || Math.abs(start.x - rect.maxX) < EPS
16
+ )
17
+ }
18
+
19
+ if (isHorizontal) {
20
+ return (
21
+ Math.abs(start.y - rect.minY) < EPS || Math.abs(start.y - rect.maxY) < EPS
22
+ )
23
+ }
24
+
25
+ return false
26
+ }
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.84",
4
+ "version": "0.0.86",
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/example50.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,149 @@
1
+ {
2
+ "chips": [
3
+ {
4
+ "chipId": "schematic_component_0",
5
+ "center": {
6
+ "x": -1.4,
7
+ "y": -6.6
8
+ },
9
+ "width": 1.1,
10
+ "height": 0.7789106999999991,
11
+ "pins": [
12
+ {
13
+ "pinId": "R7.1",
14
+ "x": -1.95,
15
+ "y": -6.6
16
+ },
17
+ {
18
+ "pinId": "R7.2",
19
+ "x": -0.85,
20
+ "y": -6.6
21
+ }
22
+ ],
23
+ "sectionId": "qspi"
24
+ },
25
+ {
26
+ "chipId": "schematic_component_1",
27
+ "center": {
28
+ "x": 0,
29
+ "y": -8.4
30
+ },
31
+ "width": 2.245,
32
+ "height": 1,
33
+ "pins": [
34
+ {
35
+ "pinId": "U5.1",
36
+ "x": -1.5225,
37
+ "y": -8.1
38
+ },
39
+ {
40
+ "pinId": "U5.2",
41
+ "x": -1.5225,
42
+ "y": -8.3
43
+ },
44
+ {
45
+ "pinId": "U5.3",
46
+ "x": -1.5225,
47
+ "y": -8.5
48
+ },
49
+ {
50
+ "pinId": "U5.4",
51
+ "x": -1.5225,
52
+ "y": -8.700000000000001
53
+ },
54
+ {
55
+ "pinId": "U5.5",
56
+ "x": 1.5225,
57
+ "y": -8.1
58
+ },
59
+ {
60
+ "pinId": "U5.6",
61
+ "x": 1.5225,
62
+ "y": -8.3
63
+ },
64
+ {
65
+ "pinId": "U5.7",
66
+ "x": 1.5225,
67
+ "y": -8.700000000000001
68
+ },
69
+ {
70
+ "pinId": "U5.8",
71
+ "x": 1.5225,
72
+ "y": -8.5
73
+ }
74
+ ],
75
+ "sectionId": "qspi"
76
+ }
77
+ ],
78
+ "directConnections": [],
79
+ "netConnections": [
80
+ {
81
+ "netId": "V3V3",
82
+ "pinIds": [
83
+ "R7.1",
84
+ "U5.8"
85
+ ],
86
+ "netLabelWidth": 0.6
87
+ },
88
+ {
89
+ "netId": "QSPI_CS",
90
+ "pinIds": [
91
+ "R7.2",
92
+ "U5.4"
93
+ ],
94
+ "netLabelWidth": 0.96
95
+ },
96
+ {
97
+ "netId": "QSPI_SCK",
98
+ "pinIds": [
99
+ "U5.1"
100
+ ],
101
+ "netLabelWidth": 1.08
102
+ },
103
+ {
104
+ "netId": "QSPI_DATA0",
105
+ "pinIds": [
106
+ "U5.2"
107
+ ],
108
+ "netLabelWidth": 1.32
109
+ },
110
+ {
111
+ "netId": "QSPI_DATA1",
112
+ "pinIds": [
113
+ "U5.3"
114
+ ],
115
+ "netLabelWidth": 1.32
116
+ },
117
+ {
118
+ "netId": "QSPI_DATA2",
119
+ "pinIds": [
120
+ "U5.5"
121
+ ],
122
+ "netLabelWidth": 1.32
123
+ },
124
+ {
125
+ "netId": "QSPI_DATA3",
126
+ "pinIds": [
127
+ "U5.6"
128
+ ],
129
+ "netLabelWidth": 1.32
130
+ },
131
+ {
132
+ "netId": "GND",
133
+ "pinIds": [
134
+ "U5.7"
135
+ ],
136
+ "netLabelWidth": 0.48
137
+ }
138
+ ],
139
+ "availableNetLabelOrientations": {
140
+ "V3V3": [
141
+ "y+"
142
+ ],
143
+ "GND": [
144
+ "y-"
145
+ ]
146
+ },
147
+ "maxMspPairDistance": 2.4
148
+ }
149
+
@@ -0,0 +1,196 @@
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="R7.1
5
+ x-" data-x="-1.95" data-y="-6.6" cx="122.2014128470511" cy="219.67471660916704" r="3" fill="hsl(232, 100%, 50%, 0.8)" />
6
+ </g>
7
+ <g>
8
+ <circle data-type="point" data-label="R7.2
9
+ x+" data-x="-0.8499999999999999" data-y="-6.6" cx="223.4006899950715" cy="219.67471660916704" r="3" fill="hsl(233, 100%, 50%, 0.8)" />
10
+ </g>
11
+ <g>
12
+ <circle data-type="point" data-label="U5.1
13
+ x-" data-x="-1.5225" data-y="-8.1" cx="161.5311319204863" cy="357.6737309019221" r="3" fill="hsl(203, 100%, 50%, 0.8)" />
14
+ </g>
15
+ <g>
16
+ <circle data-type="point" data-label="U5.2
17
+ x-" data-x="-1.5225" data-y="-8.3" cx="161.5311319204863" cy="376.0735994742896" r="3" fill="hsl(204, 100%, 50%, 0.8)" />
18
+ </g>
19
+ <g>
20
+ <circle data-type="point" data-label="U5.3
21
+ x-" data-x="-1.5225" data-y="-8.5" cx="161.5311319204863" cy="394.4734680466569" r="3" fill="hsl(205, 100%, 50%, 0.8)" />
22
+ </g>
23
+ <g>
24
+ <circle data-type="point" data-label="U5.4
25
+ x-" data-x="-1.5225" data-y="-8.700000000000001" cx="161.5311319204863" cy="412.87333661902426" r="3" fill="hsl(206, 100%, 50%, 0.8)" />
26
+ </g>
27
+ <g>
28
+ <circle data-type="point" data-label="U5.5
29
+ x+" data-x="1.5225" data-y="-8.1" cx="441.66913093477905" cy="357.6737309019221" r="3" fill="hsl(207, 100%, 50%, 0.8)" />
30
+ </g>
31
+ <g>
32
+ <circle data-type="point" data-label="U5.6
33
+ x+" data-x="1.5225" data-y="-8.3" cx="441.66913093477905" cy="376.0735994742896" r="3" fill="hsl(208, 100%, 50%, 0.8)" />
34
+ </g>
35
+ <g>
36
+ <circle data-type="point" data-label="U5.7
37
+ x+" data-x="1.5225" data-y="-8.700000000000001" cx="441.66913093477905" cy="412.87333661902426" r="3" fill="hsl(209, 100%, 50%, 0.8)" />
38
+ </g>
39
+ <g>
40
+ <circle data-type="point" data-label="U5.8
41
+ x+" data-x="1.5225" data-y="-8.5" cx="441.66913093477905" cy="394.4734680466569" r="3" fill="hsl(210, 100%, 50%, 0.8)" />
42
+ </g>
43
+ <g>
44
+ <circle data-type="point" data-label="anchorPoint
45
+ orientation: y+" data-x="-2.15" data-y="-6.6" cx="103.80154427468375" cy="219.67471660916704" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
46
+ </g>
47
+ <g>
48
+ <circle data-type="point" data-label="anchorPoint
49
+ orientation: x+" data-x="-0.8499999999999999" data-y="-6.6" cx="223.4006899950715" cy="219.67471660916704" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
50
+ </g>
51
+ <g>
52
+ <circle data-type="point" data-label="anchorPoint
53
+ orientation: x-" data-x="-1.5225" data-y="-8.700000000000001" cx="161.5311319204863" cy="412.87333661902426" 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="-1.5225" data-y="-8.1" cx="161.5311319204863" cy="357.6737309019221" 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="-1.5225" data-y="-8.3" cx="161.5311319204863" cy="376.0735994742896" 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="-1.5225" data-y="-8.5" cx="161.5311319204863" cy="394.4734680466569" 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="1.8225" data-y="-8.1" cx="469.2689337933301" cy="357.6737309019221" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
70
+ </g>
71
+ <g>
72
+ <circle data-type="point" data-label="anchorPoint
73
+ orientation: x+" data-x="1.9224999999999999" data-y="-8.3" cx="478.46886807951375" cy="376.0735994742896" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
74
+ </g>
75
+ <g>
76
+ <circle data-type="point" data-label="anchorPoint
77
+ orientation: y-" data-x="1.6235" data-y="-8.901" cx="450.9610645638246" cy="431.3652045342533" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
78
+ </g>
79
+ <g>
80
+ <polyline data-points="-1.95,-6.6 1.5225,-8.5" data-type="line" data-label="" points="122.2014128470511,219.67471660916704 441.66913093477905,394.4734680466569" fill="none" stroke="hsl(154, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
81
+ </g>
82
+ <g>
83
+ <polyline data-points="-0.8499999999999999,-6.6 -1.5225,-8.700000000000001" data-type="line" data-label="" points="223.4006899950715,219.67471660916704 161.5311319204863,412.87333661902426" fill="none" stroke="hsl(172, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
84
+ </g>
85
+ <g>
86
+ <polyline data-points="-1.95,-6.6 -2.15,-6.6 -2.15,-7.55 1.7225000000000004,-7.55 1.7225000000000004,-8.5 1.5225000000000002,-8.5" data-type="line" data-label="" points="122.2014128470511,219.67471660916704 103.80154427468375,219.67471660916704 103.80154427468375,307.0740923279119 460.06899950714643,307.0740923279119 460.06899950714643,394.4734680466569 441.6691309347791,394.4734680466569" fill="none" stroke="purple" stroke-width="1" />
87
+ </g>
88
+ <g>
89
+ <polyline data-points="1.5225,-8.1 1.8225,-8.1" data-type="line" data-label="" points="441.66913093477905,357.6737309019221 469.2689337933301,357.6737309019221" fill="none" stroke="purple" stroke-width="1" />
90
+ </g>
91
+ <g>
92
+ <polyline data-points="1.5225,-8.3 1.9224999999999999,-8.3" data-type="line" data-label="" points="441.66913093477905,376.0735994742896 478.46886807951375,376.0735994742896" fill="none" stroke="purple" stroke-width="1" />
93
+ </g>
94
+ <g>
95
+ <polyline data-points="1.5225,-8.700000000000001 1.6235,-8.700000000000001 1.6235,-8.901" data-type="line" data-label="" points="441.66913093477905,412.87333661902426 450.9610645638246,412.87333661902426 450.9610645638246,431.3652045342533" fill="none" stroke="purple" stroke-width="1" />
96
+ </g>
97
+ <g>
98
+ <rect data-type="rect" data-label="schematic_component_0" data-x="-1.4" data-y="-6.6" x="122.2014128470511" y="183.84508033514044" width="101.1992771480204" height="71.6592725480532" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010869642857142855" />
99
+ </g>
100
+ <g>
101
+ <rect data-type="rect" data-label="schematic_component_1" data-x="0" data-y="-8.4" x="161.5311319204863" y="339.27386232955485" width="280.13799901429275" height="91.99934286183668" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010869642857142855" />
102
+ </g>
103
+ <g>
104
+ <rect data-type="rect" data-label="netId: V3V3
105
+ globalConnNetId: connectivity_net0" data-x="-2.15" data-y="-6.3" x="94.60160998850009" y="164.47511089206512" width="18.399868572367353" height="55.19960571710192" fill="#ef444466" stroke="#ef4444" stroke-width="0.010869642857142855" />
106
+ </g>
107
+ <g>
108
+ <rect data-type="rect" data-label="netId: QSPI_CS
109
+ globalConnNetId: connectivity_net1" data-x="-0.3689999999999999" data-y="-6.6" x="223.4926893379333" y="210.4747823229834" width="88.31936914736326" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
110
+ </g>
111
+ <g>
112
+ <rect data-type="rect" data-label="netId: QSPI_CS
113
+ globalConnNetId: connectivity_net1" data-x="-2.0035" data-y="-8.700000000000001" x="73.11976343026123" y="403.6734023328406" width="88.31936914736323" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
114
+ </g>
115
+ <g>
116
+ <rect data-type="rect" data-label="netId: QSPI_SCK
117
+ globalConnNetId: connectivity_net2" data-x="-2.0635" data-y="-8.1" x="62.0798422868408" y="348.4737966157385" width="99.35929029078366" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
118
+ </g>
119
+ <g>
120
+ <rect data-type="rect" data-label="netId: QSPI_DATA0
121
+ globalConnNetId: connectivity_net3" data-x="-2.1835" data-y="-8.3" x="40" y="366.873665188106" width="121.43913257762446" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
122
+ </g>
123
+ <g>
124
+ <rect data-type="rect" data-label="netId: QSPI_DATA1
125
+ globalConnNetId: connectivity_net4" data-x="-2.1835" data-y="-8.5" x="40" y="385.27353376047324" width="121.43913257762446" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
126
+ </g>
127
+ <g>
128
+ <rect data-type="rect" data-label="netId: QSPI_DATA2
129
+ globalConnNetId: connectivity_net5" data-x="2.4835000000000003" data-y="-8.1" x="469.36093313619193" y="348.4737966157385" width="121.43913257762443" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
130
+ </g>
131
+ <g>
132
+ <rect data-type="rect" data-label="netId: QSPI_DATA3
133
+ globalConnNetId: connectivity_net6" data-x="2.5835" data-y="-8.3" x="478.56086742237557" y="366.873665188106" width="121.43913257762443" height="18.399868572367268" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010869642857142855" />
134
+ </g>
135
+ <g>
136
+ <rect data-type="rect" data-label="netId: GND
137
+ globalConnNetId: connectivity_net7" data-x="1.6235" data-y="-9.141" x="441.76113027764086" y="431.3652045342533" width="18.39986857236738" height="44.159684573681716" fill="#00000066" stroke="#000000" stroke-width="0.010869642857142855" />
138
+ </g>
139
+ <g id="crosshair" style="display: none">
140
+ <line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
141
+ <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>
142
+ </g>
143
+ <script>
144
+ <![CDATA[
145
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
146
+ const svg = e.currentTarget;
147
+ const rect = svg.getBoundingClientRect();
148
+ const x = e.clientX - rect.left;
149
+ const y = e.clientY - rect.top;
150
+ const crosshair = svg.getElementById('crosshair');
151
+ const h = svg.getElementById('crosshair-h');
152
+ const v = svg.getElementById('crosshair-v');
153
+ const coords = svg.getElementById('coordinates');
154
+
155
+ crosshair.style.display = 'block';
156
+ h.setAttribute('x1', '0');
157
+ h.setAttribute('x2', '640');
158
+ h.setAttribute('y1', y);
159
+ h.setAttribute('y2', y);
160
+ v.setAttribute('x1', x);
161
+ v.setAttribute('x2', x);
162
+ v.setAttribute('y1', '0');
163
+ v.setAttribute('y2', '640');
164
+
165
+ // Calculate real coordinates using inverse transformation
166
+ const matrix = {
167
+ "a": 91.99934286183671,
168
+ "c": 0,
169
+ "e": 301.6001314276327,
170
+ "b": 0,
171
+ "d": -91.99934286183671,
172
+ "f": -387.5209462789552
173
+ };
174
+ // Manually invert and apply the affine transform
175
+ // Since we only use translate and scale, we can directly compute:
176
+ // x' = (x - tx) / sx
177
+ // y' = (y - ty) / sy
178
+ const sx = matrix.a;
179
+ const sy = matrix.d;
180
+ const tx = matrix.e;
181
+ const ty = matrix.f;
182
+ const realPoint = {
183
+ x: (x - tx) / sx,
184
+ y: (y - ty) / sy // Flip y back since we used negative scale
185
+ }
186
+
187
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
188
+ coords.setAttribute('x', (x + 5).toString());
189
+ coords.setAttribute('y', (y - 5).toString());
190
+ });
191
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
192
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
193
+ });
194
+ ]]>
195
+ </script>
196
+ </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/example50.json"
4
+ import "tests/fixtures/matcher"
5
+
6
+ test("example49", () => {
7
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
8
+
9
+ solver.solve()
10
+
11
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
12
+ })