@tscircuit/schematic-trace-solver 0.0.56 → 0.0.57

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
@@ -5487,6 +5487,14 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
5487
5487
  }
5488
5488
  return false;
5489
5489
  };
5490
+ var tracePathCrossesAnyBounds = (tracePath, bounds) => {
5491
+ for (let i = 0; i < tracePath.length - 1; i++) {
5492
+ if (segmentCrossesBoundsInterior(tracePath[i], tracePath[i + 1], bounds)) {
5493
+ return true;
5494
+ }
5495
+ }
5496
+ return false;
5497
+ };
5490
5498
  var tracePathCrossesAnyTrace = (tracePath, traceMap) => {
5491
5499
  for (const trace of Object.values(traceMap)) {
5492
5500
  const points = trace.tracePath;
@@ -5968,16 +5976,24 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
5968
5976
  labelIndex
5969
5977
  );
5970
5978
  if (boundsStatus !== "valid") return boundsStatus;
5971
- if (tracePathCrossesAnyTrace(
5972
- getConnectorTracePath(
5973
- label.anchorPoint,
5974
- candidate.anchorPoint,
5975
- candidate.orientation
5976
- ),
5977
- this.traceMap
5978
- )) {
5979
+ const connectorTrace = getConnectorTracePath(
5980
+ label.anchorPoint,
5981
+ candidate.anchorPoint,
5982
+ candidate.orientation
5983
+ );
5984
+ if (tracePathCrossesAnyTrace(connectorTrace, this.traceMap)) {
5979
5985
  return "trace-collision";
5980
5986
  }
5987
+ for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
5988
+ if (i === labelIndex) continue;
5989
+ const otherLabel = this.outputNetLabelPlacements[i];
5990
+ if (tracePathCrossesAnyBounds(
5991
+ connectorTrace,
5992
+ getRectBounds(otherLabel.center, otherLabel.width, otherLabel.height)
5993
+ )) {
5994
+ return "netlabel-collision";
5995
+ }
5996
+ }
5981
5997
  return "valid";
5982
5998
  }
5983
5999
  getBoundsStatus(bounds, labelIndex) {
@@ -21,6 +21,7 @@ import {
21
21
  rangesOverlap,
22
22
  rectsOverlap,
23
23
  traceCrossesBoundsInterior,
24
+ tracePathCrossesAnyBounds,
24
25
  tracePathCrossesAnyTrace,
25
26
  } from "./geometry"
26
27
  import { getPinMap, getTracePins, toNetLabelPlacementPatch } from "./traces"
@@ -447,19 +448,29 @@ export class AvailableNetOrientationSolver extends BaseSolver {
447
448
  )
448
449
  if (boundsStatus !== "valid") return boundsStatus
449
450
 
450
- if (
451
- tracePathCrossesAnyTrace(
452
- getConnectorTracePath(
453
- label.anchorPoint,
454
- candidate.anchorPoint,
455
- candidate.orientation,
456
- ),
457
- this.traceMap,
458
- )
459
- ) {
451
+ const connectorTrace = getConnectorTracePath(
452
+ label.anchorPoint,
453
+ candidate.anchorPoint,
454
+ candidate.orientation,
455
+ )
456
+
457
+ if (tracePathCrossesAnyTrace(connectorTrace, this.traceMap)) {
460
458
  return "trace-collision"
461
459
  }
462
460
 
461
+ for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
462
+ if (i === labelIndex) continue
463
+ const otherLabel = this.outputNetLabelPlacements[i]!
464
+ if (
465
+ tracePathCrossesAnyBounds(
466
+ connectorTrace,
467
+ getRectBounds(otherLabel.center, otherLabel.width, otherLabel.height),
468
+ )
469
+ ) {
470
+ return "netlabel-collision"
471
+ }
472
+ }
473
+
463
474
  return "valid"
464
475
  }
465
476
 
@@ -88,6 +88,20 @@ const segmentCrossesBoundsInterior = (p1: Point, p2: Point, bounds: Bounds) => {
88
88
  return false
89
89
  }
90
90
 
91
+ export const tracePathCrossesAnyBounds = (
92
+ tracePath: Point[],
93
+ bounds: Bounds,
94
+ ) => {
95
+ for (let i = 0; i < tracePath.length - 1; i++) {
96
+ if (
97
+ segmentCrossesBoundsInterior(tracePath[i]!, tracePath[i + 1]!, bounds)
98
+ ) {
99
+ return true
100
+ }
101
+ }
102
+ return false
103
+ }
104
+
91
105
  export const tracePathCrossesAnyTrace = (
92
106
  tracePath: Point[],
93
107
  traceMap: Record<string, SolvedTracePath>,
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.56",
4
+ "version": "0.0.57",
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/example34.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,61 @@
1
+ {
2
+ "chips": [
3
+ {
4
+ "chipId": "schematic_component_0",
5
+ "center": {
6
+ "x": 0,
7
+ "y": 0
8
+ },
9
+ "width": 1,
10
+ "height": 1,
11
+ "pins": [
12
+ {
13
+ "pinId": "U1.1",
14
+ "x": 1.1,
15
+ "y": 0.30000000000000004
16
+ },
17
+ {
18
+ "pinId": "U1.2",
19
+ "x": 1.1,
20
+ "y": 0.09999999999999998
21
+ },
22
+ {
23
+ "pinId": "U1.3",
24
+ "x": 1.1,
25
+ "y": -0.10000000000000003
26
+ },
27
+ {
28
+ "pinId": "U1.4",
29
+ "x": 1.1,
30
+ "y": -0.30000000000000004
31
+ }
32
+ ]
33
+ }
34
+ ],
35
+ "directConnections": [],
36
+ "netConnections": [
37
+ {
38
+ "netId": "SCL",
39
+ "pinIds": ["U1.1"]
40
+ },
41
+ {
42
+ "netId": "SDA",
43
+ "pinIds": ["U1.2"]
44
+ },
45
+ {
46
+ "netId": "V3_3",
47
+ "pinIds": ["U1.3"]
48
+ },
49
+ {
50
+ "netId": "GND",
51
+ "pinIds": ["U1.4"]
52
+ }
53
+ ],
54
+ "availableNetLabelOrientations": {
55
+ "SCL": ["x-", "x+"],
56
+ "SDA": ["x-", "x+"],
57
+ "V3_3": ["y+"],
58
+ "GND": ["y-"]
59
+ },
60
+ "maxMspPairDistance": 2.4
61
+ }
@@ -0,0 +1,113 @@
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="U1.1
5
+ x+" data-x="1.1" data-y="0.30000000000000004" cx="487.83715012722644" cy="248.75318066157763" r="3" fill="hsl(319, 100%, 50%, 0.8)" />
6
+ </g>
7
+ <g>
8
+ <circle data-type="point" data-label="U1.2
9
+ x+" data-x="1.1" data-y="0.09999999999999998" cx="487.83715012722644" cy="289.46564885496184" r="3" fill="hsl(320, 100%, 50%, 0.8)" />
10
+ </g>
11
+ <g>
12
+ <circle data-type="point" data-label="U1.3
13
+ x+" data-x="1.1" data-y="-0.10000000000000003" cx="487.83715012722644" cy="330.17811704834605" r="3" fill="hsl(321, 100%, 50%, 0.8)" />
14
+ </g>
15
+ <g>
16
+ <circle data-type="point" data-label="U1.4
17
+ x+" data-x="1.1" data-y="-0.30000000000000004" cx="487.83715012722644" cy="370.89058524173026" r="3" fill="hsl(322, 100%, 50%, 0.8)" />
18
+ </g>
19
+ <g>
20
+ <circle data-type="point" data-label="" data-x="1.1" data-y="0.30000000000000004" cx="487.83715012722644" cy="248.75318066157763" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
21
+ </g>
22
+ <g>
23
+ <circle data-type="point" data-label="" data-x="1.1" data-y="0.09999999999999998" cx="487.83715012722644" cy="289.46564885496184" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
24
+ </g>
25
+ <g>
26
+ <circle data-type="point" data-label="" data-x="1.5510000000000002" data-y="0.4009999999999999" cx="579.6437659033079" cy="228.1933842239186" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
27
+ </g>
28
+ <g>
29
+ <circle data-type="point" data-label="" data-x="1.201" data-y="-0.5010000000000001" cx="508.39694656488547" cy="411.80661577608146" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
30
+ </g>
31
+ <g>
32
+ <polyline data-points="1.1,-0.10000000000000003 1.5510000000000002,-0.10000000000000003 1.5510000000000002,0.4009999999999999" data-type="line" data-label="" points="487.83715012722644,330.17811704834605 579.6437659033079,330.17811704834605 579.6437659033079,228.1933842239186" fill="none" stroke="purple" stroke-width="1" />
33
+ </g>
34
+ <g>
35
+ <polyline data-points="1.1,-0.30000000000000004 1.201,-0.30000000000000004 1.201,-0.5010000000000001" data-type="line" data-label="" points="487.83715012722644,370.89058524173026 508.39694656488547,370.89058524173026 508.39694656488547,411.80661577608146" fill="none" stroke="purple" stroke-width="1" />
36
+ </g>
37
+ <g>
38
+ <rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0" x="40" y="208.04071246819342" width="447.83715012722644" height="203.56234096692106" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.004912500000000001" />
39
+ </g>
40
+ <g>
41
+ <rect data-type="rect" data-label="netId: SCL
42
+ globalConnNetId: connectivity_net0" data-x="1.326" data-y="0.30000000000000004" x="488.0407124681933" y="228.39694656488552" width="91.60305343511459" height="40.71246819338421" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.004912500000000001" />
43
+ </g>
44
+ <g>
45
+ <rect data-type="rect" data-label="netId: SDA
46
+ globalConnNetId: connectivity_net1" data-x="1.326" data-y="0.09999999999999998" x="488.0407124681933" y="269.10941475826974" width="91.60305343511459" height="40.71246819338421" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.004912500000000001" />
47
+ </g>
48
+ <g>
49
+ <rect data-type="rect" data-label="netId: V3_3
50
+ globalConnNetId: connectivity_net2" data-x="1.5510000000000002" data-y="0.6259999999999999" x="559.2875318066158" y="136.59033078880412" width="40.71246819338421" height="91.60305343511448" fill="#ef444466" stroke="#ef4444" stroke-width="0.004912500000000001" />
51
+ </g>
52
+ <g>
53
+ <rect data-type="rect" data-label="netId: GND
54
+ globalConnNetId: connectivity_net3" data-x="1.201" data-y="-0.7260000000000001" x="488.0407124681933" y="411.80661577608146" width="40.71246819338421" height="91.60305343511448" fill="#00000066" stroke="#000000" stroke-width="0.004912500000000001" />
55
+ </g>
56
+ <g id="crosshair" style="display: none">
57
+ <line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
58
+ <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>
59
+ </g>
60
+ <script>
61
+ <![CDATA[
62
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
63
+ const svg = e.currentTarget;
64
+ const rect = svg.getBoundingClientRect();
65
+ const x = e.clientX - rect.left;
66
+ const y = e.clientY - rect.top;
67
+ const crosshair = svg.getElementById('crosshair');
68
+ const h = svg.getElementById('crosshair-h');
69
+ const v = svg.getElementById('crosshair-v');
70
+ const coords = svg.getElementById('coordinates');
71
+
72
+ crosshair.style.display = 'block';
73
+ h.setAttribute('x1', '0');
74
+ h.setAttribute('x2', '640');
75
+ h.setAttribute('y1', y);
76
+ h.setAttribute('y2', y);
77
+ v.setAttribute('x1', x);
78
+ v.setAttribute('x2', x);
79
+ v.setAttribute('y1', '0');
80
+ v.setAttribute('y2', '640');
81
+
82
+ // Calculate real coordinates using inverse transformation
83
+ const matrix = {
84
+ "a": 203.56234096692108,
85
+ "c": 0,
86
+ "e": 263.9185750636132,
87
+ "b": 0,
88
+ "d": -203.56234096692108,
89
+ "f": 309.82188295165395
90
+ };
91
+ // Manually invert and apply the affine transform
92
+ // Since we only use translate and scale, we can directly compute:
93
+ // x' = (x - tx) / sx
94
+ // y' = (y - ty) / sy
95
+ const sx = matrix.a;
96
+ const sy = matrix.d;
97
+ const tx = matrix.e;
98
+ const ty = matrix.f;
99
+ const realPoint = {
100
+ x: (x - tx) / sx,
101
+ y: (y - ty) / sy // Flip y back since we used negative scale
102
+ }
103
+
104
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
105
+ coords.setAttribute('x', (x + 5).toString());
106
+ coords.setAttribute('y', (y - 5).toString());
107
+ });
108
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
109
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
110
+ });
111
+ ]]>
112
+ </script>
113
+ </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/example34.json"
4
+ import "tests/fixtures/matcher"
5
+
6
+ test("example34", () => {
7
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
8
+
9
+ solver.solve()
10
+
11
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
12
+ })