@tscircuit/schematic-trace-solver 0.0.54 → 0.0.55

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
@@ -56,6 +56,7 @@ type FacingDirection = "x+" | "x-" | "y+" | "y-";
56
56
  type ChipId = string;
57
57
  type PinId = string;
58
58
  type NetId = string;
59
+ type SectionId = string;
59
60
  interface InputPin {
60
61
  pinId: PinId;
61
62
  x: number;
@@ -71,6 +72,7 @@ interface InputChip {
71
72
  width: number;
72
73
  height: number;
73
74
  pins: Array<InputPin>;
75
+ sectionId?: SectionId;
74
76
  }
75
77
  interface InputDirectConnection {
76
78
  pinIds: [PinId, PinId];
@@ -868,4 +870,4 @@ declare class SchematicTracePipelineSolver extends BaseSolver {
868
870
  preview(): GraphicsObject;
869
871
  }
870
872
 
871
- export { type ChipId, type InputChip, type InputDirectConnection, type InputNetConnection, type InputPin, type InputProblem, type NetId, type PinId, SchematicTracePipelineSolver, type SchematicTracePipelineSolverParams, SchematicTraceSingleLineSolver2 };
873
+ export { type ChipId, type InputChip, type InputDirectConnection, type InputNetConnection, type InputPin, type InputProblem, type NetId, type PinId, SchematicTracePipelineSolver, type SchematicTracePipelineSolverParams, SchematicTraceSingleLineSolver2, type SectionId };
package/dist/index.js CHANGED
@@ -301,6 +301,30 @@ var getColorFromString = (string, alpha = 1) => {
301
301
  return `hsl(${hash % 360}, 100%, 50%, ${alpha})`;
302
302
  };
303
303
 
304
+ // lib/utils/arePinsInDifferentSchematicSections.ts
305
+ var getSectionNameForPin = (sectionByChipId, sectionByPinId, pin) => {
306
+ if (pin.chipId) {
307
+ const chipSection = sectionByChipId.get(pin.chipId);
308
+ if (chipSection) return chipSection;
309
+ }
310
+ return sectionByPinId.get(pin.pinId);
311
+ };
312
+ var arePinsInDifferentSchematicSections = (inputProblem, p1, p2) => {
313
+ const sectionByChipId = /* @__PURE__ */ new Map();
314
+ const sectionByPinId = /* @__PURE__ */ new Map();
315
+ for (const chip of inputProblem.chips) {
316
+ if (!chip.sectionId) continue;
317
+ sectionByChipId.set(chip.chipId, chip.sectionId);
318
+ for (const pin of chip.pins) {
319
+ sectionByPinId.set(pin.pinId, chip.sectionId);
320
+ }
321
+ }
322
+ if (sectionByChipId.size === 0) return false;
323
+ const s1 = getSectionNameForPin(sectionByChipId, sectionByPinId, p1);
324
+ const s2 = getSectionNameForPin(sectionByChipId, sectionByPinId, p2);
325
+ return !!s1 && !!s2 && s1 !== s2;
326
+ };
327
+
304
328
  // lib/solvers/SchematicTracePipelineSolver/visualizeInputProblem.ts
305
329
  var visualizeInputProblem = (inputProblem, opts = {}) => {
306
330
  const { connectionAlpha = 0.8, chipAlpha = 0.8 } = opts;
@@ -337,6 +361,9 @@ ${pin._facingDirection ?? getPinDirection(pin, chip)}`,
337
361
  const [pinId1, pinId2] = directConn.pinIds;
338
362
  const pin1 = pinIdMap.get(pinId1);
339
363
  const pin2 = pinIdMap.get(pinId2);
364
+ if (arePinsInDifferentSchematicSections(inputProblem, pin1, pin2)) {
365
+ continue;
366
+ }
340
367
  graphics.lines.push({
341
368
  points: [
342
369
  {
@@ -360,6 +387,9 @@ ${pin._facingDirection ?? getPinDirection(pin, chip)}`,
360
387
  for (let j = i + 1; j < pins.length; j++) {
361
388
  const pin1 = pins[i];
362
389
  const pin2 = pins[j];
390
+ if (arePinsInDifferentSchematicSections(inputProblem, pin1, pin2)) {
391
+ continue;
392
+ }
363
393
  graphics.lines.push({
364
394
  points: [
365
395
  { x: pin1.x, y: pin1.y },
@@ -441,6 +471,9 @@ var MspConnectionPairSolver = class extends BaseSolver {
441
471
  if (manhattanDist > this.maxMspPairDistance) {
442
472
  return;
443
473
  }
474
+ if (arePinsInDifferentSchematicSections(this.inputProblem, p1, p2)) {
475
+ return;
476
+ }
444
477
  const pinIdMap2 = new Map(Object.entries(this.pinMap));
445
478
  if (doesPairCrossRestrictedCenterLines({
446
479
  inputProblem: this.inputProblem,
@@ -467,7 +500,11 @@ var MspConnectionPairSolver = class extends BaseSolver {
467
500
  directlyConnectedPins.map((p) => this.pinMap[p]).filter(Boolean),
468
501
  {
469
502
  maxDistance: this.maxMspPairDistance,
470
- forbidEdge: (a, b) => doesPairCrossRestrictedCenterLines({
503
+ forbidEdge: (a, b) => arePinsInDifferentSchematicSections(
504
+ this.inputProblem,
505
+ a,
506
+ b
507
+ ) || doesPairCrossRestrictedCenterLines({
471
508
  inputProblem: this.inputProblem,
472
509
  chipMap: this.chipMap,
473
510
  pinIdMap,
@@ -479,6 +516,9 @@ var MspConnectionPairSolver = class extends BaseSolver {
479
516
  for (const [pin1, pin2] of msp) {
480
517
  const p1Obj = this.pinMap[pin1];
481
518
  const p2Obj = this.pinMap[pin2];
519
+ if (arePinsInDifferentSchematicSections(this.inputProblem, p1Obj, p2Obj)) {
520
+ continue;
521
+ }
482
522
  if (doesPairCrossRestrictedCenterLines({
483
523
  inputProblem: this.inputProblem,
484
524
  chipMap: this.chipMap,
@@ -3461,6 +3501,9 @@ var LongDistancePairSolver = class extends BaseSolver {
3461
3501
  }).sort((a, b) => a.distance - b.distance).slice(0, NEAREST_NEIGHBOR_COUNT);
3462
3502
  for (const neighbor of neighbors) {
3463
3503
  const pair = [sourcePin, neighbor.pin];
3504
+ if (arePinsInDifferentSchematicSections(inputProblem, pair[0], pair[1])) {
3505
+ continue;
3506
+ }
3464
3507
  const pairKey = pair.map((p) => p.pinId).sort().join("--");
3465
3508
  if (!addedPairKeys.has(pairKey)) {
3466
3509
  candidatePairs.push(pair);
@@ -3559,7 +3602,10 @@ var LongDistancePairSolver = class extends BaseSolver {
3559
3602
  }
3560
3603
  getOutput() {
3561
3604
  if (!this.solved) {
3562
- return { newTraces: [], allTracesMerged: this.params.alreadySolvedTraces };
3605
+ return {
3606
+ newTraces: [],
3607
+ allTracesMerged: this.params.alreadySolvedTraces
3608
+ };
3563
3609
  }
3564
3610
  return {
3565
3611
  newTraces: this.solvedLongDistanceTraces,
@@ -12,6 +12,7 @@ import { doesTraceOverlapWithExistingTraces } from "lib/utils/does-trace-overlap
12
12
  import { visualizeInputProblem } from "../SchematicTracePipelineSolver/visualizeInputProblem"
13
13
  import type { SolvedTracePath } from "../SchematicTraceLinesSolver/SchematicTraceLinesSolver"
14
14
  import type { ConnectivityMap } from "connectivity-map"
15
+ import { arePinsInDifferentSchematicSections } from "../../utils/arePinsInDifferentSchematicSections"
15
16
 
16
17
  const NEAREST_NEIGHBOR_COUNT = 3
17
18
 
@@ -104,6 +105,11 @@ export class LongDistancePairSolver extends BaseSolver {
104
105
  InputPin & { chipId: string },
105
106
  InputPin & { chipId: string },
106
107
  ] = [sourcePin, neighbor.pin]
108
+ if (
109
+ arePinsInDifferentSchematicSections(inputProblem, pair[0], pair[1])
110
+ ) {
111
+ continue
112
+ }
107
113
  const pairKey = pair
108
114
  .map((p) => p.pinId)
109
115
  .sort()
@@ -225,7 +231,10 @@ export class LongDistancePairSolver extends BaseSolver {
225
231
  allTracesMerged: SolvedTracePath[]
226
232
  } {
227
233
  if (!this.solved) {
228
- return { newTraces: [], allTracesMerged: this.params.alreadySolvedTraces }
234
+ return {
235
+ newTraces: [],
236
+ allTracesMerged: this.params.alreadySolvedTraces,
237
+ }
229
238
  }
230
239
  return {
231
240
  newTraces: this.solvedLongDistanceTraces,
@@ -12,6 +12,7 @@ import { doesPairCrossRestrictedCenterLines } from "./doesPairCrossRestrictedCen
12
12
  import type { GraphicsObject } from "graphics-debug"
13
13
  import { getColorFromString } from "lib/utils/getColorFromString"
14
14
  import { visualizeInputProblem } from "../SchematicTracePipelineSolver/visualizeInputProblem"
15
+ import { arePinsInDifferentSchematicSections } from "../../utils/arePinsInDifferentSchematicSections"
15
16
 
16
17
  export type MspConnectionPairId = string
17
18
 
@@ -110,6 +111,9 @@ export class MspConnectionPairSolver extends BaseSolver {
110
111
  // Too far apart; skip creating an MSP pair for this net
111
112
  return
112
113
  }
114
+ if (arePinsInDifferentSchematicSections(this.inputProblem, p1, p2)) {
115
+ return
116
+ }
113
117
  // Avoid pairs that would cross restricted center lines
114
118
  const pinIdMap = new Map(Object.entries(this.pinMap)) as Map<
115
119
  PinId,
@@ -153,6 +157,11 @@ export class MspConnectionPairSolver extends BaseSolver {
153
157
  {
154
158
  maxDistance: this.maxMspPairDistance,
155
159
  forbidEdge: (a, b) =>
160
+ arePinsInDifferentSchematicSections(
161
+ this.inputProblem,
162
+ a as InputPin & { chipId: string },
163
+ b as InputPin & { chipId: string },
164
+ ) ||
156
165
  doesPairCrossRestrictedCenterLines({
157
166
  inputProblem: this.inputProblem,
158
167
  chipMap: this.chipMap,
@@ -166,6 +175,11 @@ export class MspConnectionPairSolver extends BaseSolver {
166
175
  for (const [pin1, pin2] of msp) {
167
176
  const p1Obj = this.pinMap[pin1!]!
168
177
  const p2Obj = this.pinMap[pin2!]!
178
+ if (
179
+ arePinsInDifferentSchematicSections(this.inputProblem, p1Obj, p2Obj)
180
+ ) {
181
+ continue
182
+ }
169
183
  // Skip any edge that would cross a restricted center line (safety filter)
170
184
  if (
171
185
  doesPairCrossRestrictedCenterLines({
@@ -2,6 +2,7 @@ import type { GraphicsObject } from "graphics-debug"
2
2
  import type { PinId, InputPin, InputProblem } from "lib/types/InputProblem"
3
3
  import { getColorFromString } from "lib/utils/getColorFromString"
4
4
  import { getPinDirection } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/getPinDirection"
5
+ import { arePinsInDifferentSchematicSections } from "../../utils/arePinsInDifferentSchematicSections"
5
6
 
6
7
  export const visualizeInputProblem = (
7
8
  inputProblem: InputProblem,
@@ -50,6 +51,9 @@ export const visualizeInputProblem = (
50
51
  const [pinId1, pinId2] = directConn.pinIds
51
52
  const pin1 = pinIdMap.get(pinId1)!
52
53
  const pin2 = pinIdMap.get(pinId2)!
54
+ if (arePinsInDifferentSchematicSections(inputProblem, pin1, pin2)) {
55
+ continue
56
+ }
53
57
  graphics.lines.push({
54
58
  points: [
55
59
  {
@@ -74,6 +78,9 @@ export const visualizeInputProblem = (
74
78
  for (let j = i + 1; j < pins.length; j++) {
75
79
  const pin1 = pins[i]!
76
80
  const pin2 = pins[j]!
81
+ if (arePinsInDifferentSchematicSections(inputProblem, pin1, pin2)) {
82
+ continue
83
+ }
77
84
  graphics.lines.push({
78
85
  points: [
79
86
  { x: pin1.x, y: pin1.y },
@@ -4,6 +4,7 @@ import type { FacingDirection } from "lib/utils/dir"
4
4
  export type ChipId = string
5
5
  export type PinId = string
6
6
  export type NetId = string
7
+ export type SectionId = string
7
8
 
8
9
  export interface InputPin {
9
10
  pinId: PinId
@@ -18,6 +19,7 @@ export interface InputChip {
18
19
  width: number
19
20
  height: number
20
21
  pins: Array<InputPin>
22
+ sectionId?: SectionId
21
23
  }
22
24
  export interface InputDirectConnection {
23
25
  pinIds: [PinId, PinId]
@@ -0,0 +1,39 @@
1
+ import type { InputProblem, InputPin } from "lib/types/InputProblem"
2
+
3
+ const getSectionNameForPin = (
4
+ sectionByChipId: Map<string, string>,
5
+ sectionByPinId: Map<string, string>,
6
+ pin: InputPin & { chipId?: string },
7
+ ) => {
8
+ if (pin.chipId) {
9
+ const chipSection = sectionByChipId.get(pin.chipId)
10
+ if (chipSection) return chipSection
11
+ }
12
+
13
+ return sectionByPinId.get(pin.pinId)
14
+ }
15
+
16
+ export const arePinsInDifferentSchematicSections = (
17
+ inputProblem: InputProblem,
18
+ p1: InputPin & { chipId?: string },
19
+ p2: InputPin & { chipId?: string },
20
+ ) => {
21
+ const sectionByChipId = new Map<string, string>()
22
+ const sectionByPinId = new Map<string, string>()
23
+
24
+ for (const chip of inputProblem.chips) {
25
+ if (!chip.sectionId) continue
26
+
27
+ sectionByChipId.set(chip.chipId, chip.sectionId)
28
+ for (const pin of chip.pins) {
29
+ sectionByPinId.set(pin.pinId, chip.sectionId)
30
+ }
31
+ }
32
+
33
+ if (sectionByChipId.size === 0) return false
34
+
35
+ const s1 = getSectionNameForPin(sectionByChipId, sectionByPinId, p1)
36
+ const s2 = getSectionNameForPin(sectionByChipId, sectionByPinId, p2)
37
+
38
+ return !!s1 && !!s2 && s1 !== s2
39
+ }
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.54",
4
+ "version": "0.0.55",
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/example32.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,148 @@
1
+ {
2
+ "chips": [
3
+ {
4
+ "chipId": "schematic_component_0",
5
+ "center": { "x": -4, "y": 3 },
6
+ "width": 0.95,
7
+ "height": 0.29,
8
+ "sectionId": "power",
9
+ "pins": [
10
+ { "pinId": "B1.1", "x": -4.45, "y": 2.9699999999999998 },
11
+ { "pinId": "B1.2", "x": -3.55, "y": 2.9699999999999998 }
12
+ ]
13
+ },
14
+ {
15
+ "chipId": "schematic_component_1",
16
+ "center": { "x": -2, "y": 3 },
17
+ "width": 0.76,
18
+ "height": 0.5,
19
+ "sectionId": "power",
20
+ "pins": [
21
+ { "pinId": "SW1.1", "x": -2.38, "y": 3 },
22
+ { "pinId": "SW1.2", "x": -1.62, "y": 3 }
23
+ ]
24
+ },
25
+ {
26
+ "chipId": "schematic_component_2",
27
+ "center": { "x": -3, "y": 1.5 },
28
+ "width": 1.1,
29
+ "height": 0.84,
30
+ "sectionId": "power",
31
+ "pins": [
32
+ { "pinId": "C3.1", "x": -3.55, "y": 1.5 },
33
+ { "pinId": "C3.2", "x": -2.45, "y": 1.5 }
34
+ ]
35
+ },
36
+ {
37
+ "chipId": "schematic_component_3",
38
+ "center": { "x": 1.5, "y": 2.5 },
39
+ "width": 1.6,
40
+ "height": 1,
41
+ "sectionId": "timer",
42
+ "pins": [
43
+ { "pinId": "U1.1", "x": 2.7, "y": 2.2 },
44
+ { "pinId": "U1.2", "x": 0.2999999999999998, "y": 2.2 },
45
+ { "pinId": "U1.3", "x": 2.7, "y": 2.6 },
46
+ { "pinId": "U1.4", "x": 0.2999999999999998, "y": 2.8 },
47
+ { "pinId": "U1.5", "x": 0.2999999999999998, "y": 2.6 },
48
+ { "pinId": "U1.6", "x": 0.2999999999999998, "y": 2.4 },
49
+ { "pinId": "U1.7", "x": 2.7, "y": 2.4 },
50
+ { "pinId": "U1.8", "x": 2.7, "y": 2.8 }
51
+ ]
52
+ },
53
+ {
54
+ "chipId": "schematic_component_4",
55
+ "center": { "x": 4, "y": 1.5 },
56
+ "width": 1.1,
57
+ "height": 0.84,
58
+ "sectionId": "timer",
59
+ "pins": [
60
+ { "pinId": "C2.1", "x": 3.45, "y": 1.5 },
61
+ { "pinId": "C2.2", "x": 4.55, "y": 1.5 }
62
+ ]
63
+ },
64
+ {
65
+ "chipId": "schematic_component_5",
66
+ "center": { "x": -4, "y": -1.5 },
67
+ "width": 1.1,
68
+ "height": 0.388910699999999,
69
+ "sectionId": "timing-network",
70
+ "pins": [
71
+ { "pinId": "R1.1", "x": -4.55, "y": -1.5 },
72
+ { "pinId": "R1.2", "x": -3.4499999999999997, "y": -1.5 }
73
+ ]
74
+ },
75
+ {
76
+ "chipId": "schematic_component_6",
77
+ "center": { "x": -2, "y": -1.5 },
78
+ "width": 1.1,
79
+ "height": 0.388910699999999,
80
+ "sectionId": "timing-network",
81
+ "pins": [
82
+ { "pinId": "R2.1", "x": -2.55, "y": -1.5 },
83
+ { "pinId": "R2.2", "x": -1.4500000000000002, "y": -1.5 }
84
+ ]
85
+ },
86
+ {
87
+ "chipId": "schematic_component_7",
88
+ "center": { "x": -3, "y": -3 },
89
+ "width": 1.1,
90
+ "height": 0.84,
91
+ "sectionId": "timing-network",
92
+ "pins": [
93
+ { "pinId": "C1.1", "x": -3.55, "y": -3 },
94
+ { "pinId": "C1.2", "x": -2.45, "y": -3 }
95
+ ]
96
+ },
97
+ {
98
+ "chipId": "schematic_component_8",
99
+ "center": { "x": 2.5, "y": -1.5 },
100
+ "width": 1.1,
101
+ "height": 0.388910699999999,
102
+ "sectionId": "output",
103
+ "pins": [
104
+ { "pinId": "R3.1", "x": 1.95, "y": -1.5 },
105
+ { "pinId": "R3.2", "x": 3.05, "y": -1.5 }
106
+ ]
107
+ },
108
+ {
109
+ "chipId": "schematic_component_9",
110
+ "center": { "x": 4.5, "y": -1.5 },
111
+ "width": 1.13,
112
+ "height": 0.65,
113
+ "sectionId": "output",
114
+ "pins": [
115
+ { "pinId": "D1.1", "x": 3.96, "y": -1.5 },
116
+ { "pinId": "D1.2", "x": 5.04, "y": -1.5 }
117
+ ]
118
+ }
119
+ ],
120
+ "directConnections": [
121
+ { "pinIds": ["B1.1", "SW1.1"], "netId": ".B1 > .pin1 to .SW1 > .pin1" },
122
+ { "pinIds": ["U1.5", "C2.1"], "netId": ".U1 > .CTRL to .C2 > .pin1" },
123
+ { "pinIds": ["U1.6", "U1.2"], "netId": ".U1 > .THRES to .U1 > .TRIG" },
124
+ { "pinIds": ["R1.2", "U1.7"], "netId": ".R1 > .pin2 to .U1 > .DISCH" },
125
+ { "pinIds": ["U1.7", "R2.1"], "netId": ".U1 > .DISCH to .R2 > .pin1" },
126
+ { "pinIds": ["R2.2", "U1.6"], "netId": ".R2 > .pin2 to .U1 > .THRES" },
127
+ { "pinIds": ["U1.6", "C1.1"], "netId": ".U1 > .THRES to .C1 > .pin1" },
128
+ { "pinIds": ["U1.3", "R3.1"], "netId": ".U1 > .OUT to .R3 > .pin1" },
129
+ { "pinIds": ["R3.2", "D1.1"], "netId": ".R3 > .pin2 to .D1 > .pin1" }
130
+ ],
131
+ "netConnections": [
132
+ {
133
+ "netId": "GND",
134
+ "pinIds": ["B1.2", "C3.2", "U1.1", "C2.2", "C1.2", "D1.2"],
135
+ "netLabelWidth": 0.3
136
+ },
137
+ {
138
+ "netId": "VCC",
139
+ "pinIds": ["SW1.2", "C3.1", "U1.4", "U1.8", "R1.1"],
140
+ "netLabelWidth": 0.3
141
+ }
142
+ ],
143
+ "availableNetLabelOrientations": {
144
+ "VCC": ["y+"],
145
+ "GND": ["y-"]
146
+ },
147
+ "maxMspPairDistance": 2.4
148
+ }
@@ -0,0 +1,391 @@
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="B1.1
5
+ x-" data-x="-4.475" data-y="2.9699999999999998" cx="64.53944811504081" cy="160.57520404197436" r="3" fill="hsl(210, 100%, 50%, 0.8)" />
6
+ </g>
7
+ <g>
8
+ <circle data-type="point" data-label="B1.2
9
+ x+" data-x="-3.525" data-y="2.9699999999999998" cx="116.23008161678973" cy="160.57520404197436" r="3" fill="hsl(211, 100%, 50%, 0.8)" />
10
+ </g>
11
+ <g>
12
+ <circle data-type="point" data-label="SW1.1
13
+ x-" data-x="-2.38" data-y="3" cx="178.5308977846871" cy="158.94286824718228" r="3" fill="hsl(104, 100%, 50%, 0.8)" />
14
+ </g>
15
+ <g>
16
+ <circle data-type="point" data-label="SW1.2
17
+ x+" data-x="-1.62" data-y="3" cx="219.88340458608627" cy="158.94286824718228" r="3" fill="hsl(105, 100%, 50%, 0.8)" />
18
+ </g>
19
+ <g>
20
+ <circle data-type="point" data-label="C3.1
21
+ x-" data-x="-3.55" data-y="1.5" cx="114.86980178779635" cy="240.55965798678585" r="3" fill="hsl(243, 100%, 50%, 0.8)" />
22
+ </g>
23
+ <g>
24
+ <circle data-type="point" data-label="C3.2
25
+ x+" data-x="-2.45" data-y="1.5" cx="174.7221142635056" cy="240.55965798678585" r="3" fill="hsl(244, 100%, 50%, 0.8)" />
26
+ </g>
27
+ <g>
28
+ <circle data-type="point" data-label="U1.1
29
+ x+" data-x="2.7" data-y="2.2" cx="454.93975903614455" cy="202.47182277497086" r="3" fill="hsl(319, 100%, 50%, 0.8)" />
30
+ </g>
31
+ <g>
32
+ <circle data-type="point" data-label="U1.2
33
+ x-" data-x="0.2999999999999998" data-y="2.2" cx="324.35289545277885" cy="202.47182277497086" r="3" fill="hsl(320, 100%, 50%, 0.8)" />
34
+ </g>
35
+ <g>
36
+ <circle data-type="point" data-label="U1.3
37
+ x+" data-x="2.7" data-y="2.6" cx="454.93975903614455" cy="180.70734551107657" r="3" fill="hsl(321, 100%, 50%, 0.8)" />
38
+ </g>
39
+ <g>
40
+ <circle data-type="point" data-label="U1.4
41
+ x-" data-x="0.2999999999999998" data-y="2.8" cx="324.35289545277885" cy="169.82510687912944" r="3" fill="hsl(322, 100%, 50%, 0.8)" />
42
+ </g>
43
+ <g>
44
+ <circle data-type="point" data-label="U1.5
45
+ x-" data-x="0.2999999999999998" data-y="2.6" cx="324.35289545277885" cy="180.70734551107657" r="3" fill="hsl(323, 100%, 50%, 0.8)" />
46
+ </g>
47
+ <g>
48
+ <circle data-type="point" data-label="U1.6
49
+ x-" data-x="0.2999999999999998" data-y="2.4" cx="324.35289545277885" cy="191.5895841430237" r="3" fill="hsl(324, 100%, 50%, 0.8)" />
50
+ </g>
51
+ <g>
52
+ <circle data-type="point" data-label="U1.7
53
+ x+" data-x="2.7" data-y="2.4" cx="454.93975903614455" cy="191.5895841430237" r="3" fill="hsl(325, 100%, 50%, 0.8)" />
54
+ </g>
55
+ <g>
56
+ <circle data-type="point" data-label="U1.8
57
+ x+" data-x="2.7" data-y="2.8" cx="454.93975903614455" cy="169.82510687912944" r="3" fill="hsl(326, 100%, 50%, 0.8)" />
58
+ </g>
59
+ <g>
60
+ <circle data-type="point" data-label="C2.1
61
+ x-" data-x="3.45" data-y="1.5" cx="495.74815390594637" cy="240.55965798678585" r="3" fill="hsl(2, 100%, 50%, 0.8)" />
62
+ </g>
63
+ <g>
64
+ <circle data-type="point" data-label="C2.2
65
+ x+" data-x="4.55" data-y="1.5" cx="555.6004663816557" cy="240.55965798678585" r="3" fill="hsl(3, 100%, 50%, 0.8)" />
66
+ </g>
67
+ <g>
68
+ <circle data-type="point" data-label="R1.1
69
+ x-" data-x="-4.550000000000001" data-y="-1.5" cx="60.458608628060574" cy="403.793237465993" r="3" fill="hsl(226, 100%, 50%, 0.8)" />
70
+ </g>
71
+ <g>
72
+ <circle data-type="point" data-label="R1.2
73
+ x+" data-x="-3.4499999999999997" data-y="-1.5" cx="120.31092110376991" cy="403.793237465993" r="3" fill="hsl(227, 100%, 50%, 0.8)" />
74
+ </g>
75
+ <g>
76
+ <circle data-type="point" data-label="R2.1
77
+ x-" data-x="-2.55" data-y="-1.5" cx="169.28099494753206" cy="403.793237465993" r="3" fill="hsl(107, 100%, 50%, 0.8)" />
78
+ </g>
79
+ <g>
80
+ <circle data-type="point" data-label="R2.2
81
+ x+" data-x="-1.45" data-y="-1.5" cx="229.13330742324132" cy="403.793237465993" r="3" fill="hsl(108, 100%, 50%, 0.8)" />
82
+ </g>
83
+ <g>
84
+ <circle data-type="point" data-label="C1.1
85
+ x-" data-x="-3.55" data-y="-3" cx="114.86980178779635" cy="485.4100272055966" r="3" fill="hsl(121, 100%, 50%, 0.8)" />
86
+ </g>
87
+ <g>
88
+ <circle data-type="point" data-label="C1.2
89
+ x+" data-x="-2.45" data-y="-3" cx="174.7221142635056" cy="485.4100272055966" r="3" fill="hsl(122, 100%, 50%, 0.8)" />
90
+ </g>
91
+ <g>
92
+ <circle data-type="point" data-label="R3.1
93
+ x-" data-x="1.95" data-y="-1.5" cx="414.1313641663428" cy="403.793237465993" r="3" fill="hsl(348, 100%, 50%, 0.8)" />
94
+ </g>
95
+ <g>
96
+ <circle data-type="point" data-label="R3.2
97
+ x+" data-x="3.05" data-y="-1.5" cx="473.98367664205205" cy="403.793237465993" r="3" fill="hsl(349, 100%, 50%, 0.8)" />
98
+ </g>
99
+ <g>
100
+ <circle data-type="point" data-label="D1.1
101
+ x-" data-x="3.935" data-y="-1.5" cx="522.1375825884181" cy="403.793237465993" r="3" fill="hsl(32, 100%, 50%, 0.8)" />
102
+ </g>
103
+ <g>
104
+ <circle data-type="point" data-label="D1.2
105
+ x+" data-x="5.0649999999999995" data-y="-1.5" cx="583.6222308589195" cy="403.793237465993" r="3" fill="hsl(33, 100%, 50%, 0.8)" />
106
+ </g>
107
+ <g>
108
+ <circle data-type="point" data-label="anchorPoint
109
+ orientation: x-" data-x="-4.475" data-y="2.9699999999999998" cx="64.53944811504081" cy="160.57520404197436" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
110
+ </g>
111
+ <g>
112
+ <circle data-type="point" data-label="anchorPoint
113
+ orientation: x-" data-x="-2.38" data-y="3" cx="178.5308977846871" cy="158.94286824718228" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
114
+ </g>
115
+ <g>
116
+ <circle data-type="point" data-label="anchorPoint
117
+ orientation: y-" data-x="-2.9699999999999998" data-y="2.9699999999999998" cx="146.42829382044306" cy="160.57520404197436" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
118
+ </g>
119
+ <g>
120
+ <circle data-type="point" data-label="anchorPoint
121
+ orientation: y-" data-x="4.75" data-y="1.5" cx="566.4827050136028" cy="240.55965798678585" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
122
+ </g>
123
+ <g>
124
+ <circle data-type="point" data-label="anchorPoint
125
+ orientation: x+" data-x="-2.45" data-y="-3" cx="174.7221142635056" cy="485.4100272055966" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
126
+ </g>
127
+ <g>
128
+ <circle data-type="point" data-label="anchorPoint
129
+ orientation: x+" data-x="5.0649999999999995" data-y="-1.5" cx="583.6222308589195" cy="403.793237465993" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
130
+ </g>
131
+ <g>
132
+ <circle data-type="point" data-label="anchorPoint
133
+ orientation: x+" data-x="-1.62" data-y="3" cx="219.88340458608627" cy="158.94286824718228" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
134
+ </g>
135
+ <g>
136
+ <circle data-type="point" data-label="anchorPoint
137
+ orientation: x-" data-x="-3.55" data-y="1.5" cx="114.86980178779635" cy="240.55965798678585" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
138
+ </g>
139
+ <g>
140
+ <circle data-type="point" data-label="anchorPoint
141
+ orientation: y+" data-x="0.09999999999999981" data-y="3.2" cx="313.47065682083166" cy="148.06062961523511" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
142
+ </g>
143
+ <g>
144
+ <circle data-type="point" data-label="anchorPoint
145
+ orientation: x-" data-x="-4.550000000000001" data-y="-1.5" cx="60.458608628060574" cy="403.793237465993" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
146
+ </g>
147
+ <g>
148
+ <circle data-type="point" data-label="anchorPoint
149
+ orientation: x-" data-x="0.09999999999999981" data-y="2.4" cx="313.47065682083166" cy="191.5895841430237" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
150
+ </g>
151
+ <g>
152
+ <circle data-type="point" data-label="anchorPoint
153
+ orientation: y+" data-x="-1.25" data-y="-1.5" cx="240.01554605518848" cy="403.793237465993" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
154
+ </g>
155
+ <g>
156
+ <circle data-type="point" data-label="anchorPoint
157
+ orientation: x+" data-x="2.7" data-y="2.6" cx="454.93975903614455" cy="180.70734551107657" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
158
+ </g>
159
+ <g>
160
+ <circle data-type="point" data-label="anchorPoint
161
+ orientation: x-" data-x="1.95" data-y="-1.5" cx="414.1313641663428" cy="403.793237465993" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
162
+ </g>
163
+ <g>
164
+ <circle data-type="point" data-label="anchorPoint
165
+ orientation: x-" data-x="0.2999999999999998" data-y="2.6" cx="324.35289545277885" cy="180.70734551107657" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
166
+ </g>
167
+ <g>
168
+ <circle data-type="point" data-label="anchorPoint
169
+ orientation: x-" data-x="3.45" data-y="1.5" cx="495.74815390594637" cy="240.55965798678585" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
170
+ </g>
171
+ <g>
172
+ <circle data-type="point" data-label="anchorPoint
173
+ orientation: y+" data-x="-3" data-y="-1.5" cx="144.79595802565098" cy="403.793237465993" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
174
+ </g>
175
+ <g>
176
+ <circle data-type="point" data-label="anchorPoint
177
+ orientation: x+" data-x="2.7" data-y="2.4" cx="454.93975903614455" cy="191.5895841430237" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
178
+ </g>
179
+ <g>
180
+ <circle data-type="point" data-label="anchorPoint
181
+ orientation: y+" data-x="3.4924999999999997" data-y="-1.5" cx="498.06062961523514" cy="403.793237465993" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
182
+ </g>
183
+ <g>
184
+ <polyline data-points="-4.475,2.9699999999999998 -2.38,3" data-type="line" data-label="" points="64.53944811504081,160.57520404197436 178.5308977846871,158.94286824718228" fill="none" stroke="hsl(192, 100%, 50%, 0.8)" stroke-width="1" />
185
+ </g>
186
+ <g>
187
+ <polyline data-points="0.2999999999999998,2.6 3.45,1.5" data-type="line" data-label="" points="324.35289545277885,180.70734551107657 495.74815390594637,240.55965798678585" fill="none" stroke="hsl(120, 100%, 50%, 0.8)" stroke-width="1" />
188
+ </g>
189
+ <g>
190
+ <polyline data-points="0.2999999999999998,2.4 0.2999999999999998,2.2" data-type="line" data-label="" points="324.35289545277885,191.5895841430237 324.35289545277885,202.47182277497086" fill="none" stroke="hsl(192, 100%, 50%, 0.8)" stroke-width="1" />
191
+ </g>
192
+ <g>
193
+ <polyline data-points="3.05,-1.5 3.935,-1.5" data-type="line" data-label="" points="473.98367664205205,403.793237465993 522.1375825884181,403.793237465993" fill="none" stroke="hsl(344, 100%, 50%, 0.8)" stroke-width="1" />
194
+ </g>
195
+ <g>
196
+ <polyline data-points="-3.525,2.9699999999999998 -2.45,1.5" data-type="line" data-label="" points="116.23008161678973,160.57520404197436 174.7221142635056,240.55965798678585" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
197
+ </g>
198
+ <g>
199
+ <polyline data-points="2.7,2.2 4.55,1.5" data-type="line" data-label="" points="454.93975903614455,202.47182277497086 555.6004663816557,240.55965798678585" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
200
+ </g>
201
+ <g>
202
+ <polyline data-points="-1.62,3 -3.55,1.5" data-type="line" data-label="" points="219.88340458608627,158.94286824718228 114.86980178779635,240.55965798678585" fill="none" stroke="hsl(190, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
203
+ </g>
204
+ <g>
205
+ <polyline data-points="0.2999999999999998,2.8 2.7,2.8" data-type="line" data-label="" points="324.35289545277885,169.82510687912944 454.93975903614455,169.82510687912944" fill="none" stroke="hsl(190, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
206
+ </g>
207
+ <g>
208
+ <polyline data-points="0.2999999999999998,2.4 0.09999999999999981,2.4 0.09999999999999981,2.2 0.2999999999999998,2.2" data-type="line" data-label="" points="324.35289545277885,191.5895841430237 313.47065682083166,191.5895841430237 313.47065682083166,202.47182277497086 324.35289545277885,202.47182277497086" fill="none" stroke="purple" stroke-width="1" />
209
+ </g>
210
+ <g>
211
+ <polyline data-points="-2.55,-1.5 -3.4499999999999997,-1.5" data-type="line" data-label="" points="169.28099494753206,403.793237465993 120.31092110376991,403.793237465993" fill="none" stroke="purple" stroke-width="1" />
212
+ </g>
213
+ <g>
214
+ <polyline data-points="3.05,-1.5 3.935,-1.5" data-type="line" data-label="" points="473.98367664205205,403.793237465993 522.1375825884181,403.793237465993" fill="none" stroke="purple" stroke-width="1" />
215
+ </g>
216
+ <g>
217
+ <polyline data-points="-1.4500000000000002,-1.5 -1.25,-1.5 -1.25,-2.25 -3.75,-2.25 -3.75,-3 -3.55,-3" data-type="line" data-label="" points="229.13330742324132,403.793237465993 240.01554605518848,403.793237465993 240.01554605518848,444.60163233579476 103.98756315584919,444.60163233579476 103.98756315584919,485.4100272055966 114.86980178779635,485.4100272055966" fill="none" stroke="purple" stroke-width="1" />
218
+ </g>
219
+ <g>
220
+ <polyline data-points="-3.525,2.9699999999999998 -2.415,2.9699999999999998 -2.415,1.5 -2.45,1.5" data-type="line" data-label="" points="116.23008161678973,160.57520404197436 176.62650602409636,160.57520404197436 176.62650602409636,240.55965798678585 174.7221142635056,240.55965798678585" fill="none" stroke="purple" stroke-width="1" />
221
+ </g>
222
+ <g>
223
+ <polyline data-points="2.7,2.2 4.75,2.2 4.75,1.5 4.55,1.5" data-type="line" data-label="" points="454.93975903614455,202.47182277497086 566.4827050136028,202.47182277497086 566.4827050136028,240.55965798678585 555.6004663816557,240.55965798678585" fill="none" stroke="purple" stroke-width="1" />
224
+ </g>
225
+ <g>
226
+ <polyline data-points="0.2999999999999998,2.8 0.09999999999999981,2.8 0.09999999999999981,3.2 2.9000000000000004,3.2 2.9000000000000004,2.8 2.7,2.8" data-type="line" data-label="" points="324.35289545277885,169.82510687912944 313.47065682083166,169.82510687912944 313.47065682083166,148.06062961523511 465.82199766809174,148.06062961523511 465.82199766809174,169.82510687912944 454.93975903614455,169.82510687912944" fill="none" stroke="purple" stroke-width="1" />
227
+ </g>
228
+ <g>
229
+ <rect data-type="rect" data-label="schematic_component_0" data-x="-4" data-y="3" x="64.53944811504081" y="151.05324523902058" width="51.69063350174892" height="15.779246016323384" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
230
+ </g>
231
+ <g>
232
+ <rect data-type="rect" data-label="schematic_component_1" data-x="-2" data-y="3" x="178.5308977846871" y="145.34006995724835" width="41.35250680139916" height="27.20559657986786" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
233
+ </g>
234
+ <g>
235
+ <rect data-type="rect" data-label="schematic_component_2" data-x="-3" data-y="1.5" x="114.86980178779635" y="217.70695685969685" width="59.852312475709255" height="45.70540225417801" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
236
+ </g>
237
+ <g>
238
+ <rect data-type="rect" data-label="schematic_component_3" data-x="1.5" data-y="2.5" x="324.35289545277885" y="158.94286824718228" width="130.5868635833657" height="54.41119315973572" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
239
+ </g>
240
+ <g>
241
+ <rect data-type="rect" data-label="schematic_component_4" data-x="4" data-y="1.5" x="495.74815390594637" y="217.70695685969685" width="59.85231247570931" height="45.70540225417801" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
242
+ </g>
243
+ <g>
244
+ <rect data-type="rect" data-label="schematic_component_5" data-x="-4" data-y="-1.5" x="60.458608628060574" y="393.212689856199" width="59.85231247570934" height="21.161095219587992" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
245
+ </g>
246
+ <g>
247
+ <rect data-type="rect" data-label="schematic_component_6" data-x="-2" data-y="-1.5" x="169.28099494753206" y="393.212689856199" width="59.852312475709255" height="21.161095219587992" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
248
+ </g>
249
+ <g>
250
+ <rect data-type="rect" data-label="schematic_component_7" data-x="-3" data-y="-3" x="114.86980178779635" y="462.5573260785076" width="59.852312475709255" height="45.70540225417801" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
251
+ </g>
252
+ <g>
253
+ <rect data-type="rect" data-label="schematic_component_8" data-x="2.5" data-y="-1.5" x="414.1313641663428" y="393.212689856199" width="59.852312475709255" height="21.161095219587992" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
254
+ </g>
255
+ <g>
256
+ <rect data-type="rect" data-label="schematic_component_9" data-x="4.5" data-y="-1.5" x="522.1375825884181" y="386.1095996890789" width="61.48464827050134" height="35.36727555382822" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018378571428571428" />
257
+ </g>
258
+ <g>
259
+ <rect data-type="rect" data-label="netId: .B1 &gt; .pin1 to .SW1 &gt; .pin1
260
+ globalConnNetId: connectivity_net0" data-x="-4.701" data-y="2.9699999999999998" x="40" y="155.1340847260008" width="24.48503692188106" height="10.882238631947132" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
261
+ </g>
262
+ <g>
263
+ <rect data-type="rect" data-label="netId: .B1 &gt; .pin1 to .SW1 &gt; .pin1
264
+ globalConnNetId: connectivity_net0" data-x="-2.606" data-y="3" x="153.9914496696463" y="153.5017489312087" width="24.48503692188109" height="10.882238631947132" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
265
+ </g>
266
+ <g>
267
+ <rect data-type="rect" data-label="netId: GND
268
+ globalConnNetId: connectivity_net6" data-x="-2.9699999999999998" data-y="2.82" x="140.9871745044695" y="160.57520404197436" width="10.882238631947132" height="16.323357947920698" fill="#00000066" stroke="#000000" stroke-width="0.018378571428571428" />
269
+ </g>
270
+ <g>
271
+ <rect data-type="rect" data-label="netId: GND
272
+ globalConnNetId: connectivity_net6" data-x="4.75" data-y="1.35" x="561.0415856976292" y="240.55965798678585" width="10.882238631947075" height="16.323357947920726" fill="#00000066" stroke="#000000" stroke-width="0.018378571428571428" />
273
+ </g>
274
+ <g>
275
+ <rect data-type="rect" data-label="netId: GND
276
+ globalConnNetId: connectivity_net6" data-x="-2.2990000000000004" data-y="-3" x="174.77652545666535" y="479.968907889623" width="16.323357947920698" height="10.882238631947189" fill="#00000066" stroke="#000000" stroke-width="0.018378571428571428" />
277
+ </g>
278
+ <g>
279
+ <rect data-type="rect" data-label="netId: GND
280
+ globalConnNetId: connectivity_net6" data-x="5.216" data-y="-1.5" x="583.6766420520793" y="398.3521181500194" width="16.323357947920726" height="10.882238631947189" fill="#00000066" stroke="#000000" stroke-width="0.018378571428571428" />
281
+ </g>
282
+ <g>
283
+ <rect data-type="rect" data-label="netId: VCC
284
+ globalConnNetId: connectivity_net7" data-x="-1.4690000000000003" data-y="3" x="219.937815779246" y="153.5017489312087" width="16.323357947920698" height="10.882238631947132" fill="#ef444466" stroke="#ef4444" stroke-width="0.018378571428571428" />
285
+ </g>
286
+ <g>
287
+ <rect data-type="rect" data-label="netId: VCC
288
+ globalConnNetId: connectivity_net7" data-x="-3.7009999999999996" data-y="1.5" x="98.4920326467159" y="235.11853867081226" width="16.323357947920698" height="10.882238631947189" fill="#ef444466" stroke="#ef4444" stroke-width="0.018378571428571428" />
289
+ </g>
290
+ <g>
291
+ <rect data-type="rect" data-label="netId: VCC
292
+ globalConnNetId: connectivity_net7" data-x="0.09999999999999981" data-y="3.35" x="308.0295375048581" y="131.73727166731442" width="10.882238631947132" height="16.323357947920698" fill="#ef444466" stroke="#ef4444" stroke-width="0.018378571428571428" />
293
+ </g>
294
+ <g>
295
+ <rect data-type="rect" data-label="netId: VCC
296
+ globalConnNetId: connectivity_net7" data-x="-4.701000000000001" data-y="-1.5" x="44.08083948698004" y="398.3521181500194" width="16.323357947920783" height="10.882238631947189" fill="#ef444466" stroke="#ef4444" stroke-width="0.018378571428571428" />
297
+ </g>
298
+ <g>
299
+ <rect data-type="rect" data-label="netId: .U1 &gt; .THRES to .C1 &gt; .pin1
300
+ globalConnNetId: connectivity_net2" data-x="-0.1250000000000002" data-y="2.4" x="288.98561989895063" y="186.14846482705013" width="24.485036921881033" height="10.882238631947132" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
301
+ </g>
302
+ <g>
303
+ <rect data-type="rect" data-label="netId: .R2 &gt; .pin2 to .U1 &gt; .THRES
304
+ globalConnNetId: connectivity_net2" data-x="-1.25" data-y="-1.275" x="234.5744267392149" y="379.3082005441119" width="10.882238631947132" height="24.48503692188109" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
305
+ </g>
306
+ <g>
307
+ <rect data-type="rect" data-label="netId: .U1 &gt; .OUT to .R3 &gt; .pin1
308
+ globalConnNetId: connectivity_net4" data-x="2.926" data-y="2.6" x="454.9941702293043" y="175.26622619510297" width="24.48503692188109" height="10.88223863194716" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
309
+ </g>
310
+ <g>
311
+ <rect data-type="rect" data-label="netId: .U1 &gt; .OUT to .R3 &gt; .pin1
312
+ globalConnNetId: connectivity_net4" data-x="1.724" data-y="-1.5" x="389.59191605130195" y="398.3521181500194" width="24.48503692188109" height="10.882238631947189" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
313
+ </g>
314
+ <g>
315
+ <rect data-type="rect" data-label="netId: .U1 &gt; .CTRL to .C2 &gt; .pin1
316
+ globalConnNetId: connectivity_net1" data-x="0.07399999999999982" data-y="2.6" x="299.813447337738" y="175.26622619510297" width="24.48503692188109" height="10.88223863194716" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
317
+ </g>
318
+ <g>
319
+ <rect data-type="rect" data-label="netId: .U1 &gt; .CTRL to .C2 &gt; .pin1
320
+ globalConnNetId: connectivity_net1" data-x="3.224" data-y="1.5" x="471.2087057909056" y="235.11853867081226" width="24.485036921881033" height="10.882238631947189" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
321
+ </g>
322
+ <g>
323
+ <rect data-type="rect" data-label="netId: .U1 &gt; .DISCH to .R2 &gt; .pin1
324
+ globalConnNetId: connectivity_net3" data-x="-3" data-y="-1.275" x="139.3548387096774" y="379.3082005441119" width="10.882238631947132" height="24.48503692188109" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
325
+ </g>
326
+ <g>
327
+ <rect data-type="rect" data-label="netId: .U1 &gt; .DISCH to .R2 &gt; .pin1
328
+ globalConnNetId: connectivity_net3" data-x="2.926" data-y="2.4" x="454.9941702293043" y="186.14846482705013" width="24.48503692188109" height="10.882238631947132" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
329
+ </g>
330
+ <g>
331
+ <rect data-type="rect" data-label="netId: .R3 &gt; .pin2 to .D1 &gt; .pin1
332
+ globalConnNetId: connectivity_net5" data-x="3.4924999999999997" data-y="-1.275" x="492.6195102992615" y="379.3082005441119" width="10.882238631947189" height="24.48503692188109" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018378571428571428" />
333
+ </g>
334
+ <g id="crosshair" style="display: none">
335
+ <line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
336
+ <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>
337
+ </g>
338
+ <script>
339
+ <![CDATA[
340
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
341
+ const svg = e.currentTarget;
342
+ const rect = svg.getBoundingClientRect();
343
+ const x = e.clientX - rect.left;
344
+ const y = e.clientY - rect.top;
345
+ const crosshair = svg.getElementById('crosshair');
346
+ const h = svg.getElementById('crosshair-h');
347
+ const v = svg.getElementById('crosshair-v');
348
+ const coords = svg.getElementById('coordinates');
349
+
350
+ crosshair.style.display = 'block';
351
+ h.setAttribute('x1', '0');
352
+ h.setAttribute('x2', '640');
353
+ h.setAttribute('y1', y);
354
+ h.setAttribute('y2', y);
355
+ v.setAttribute('x1', x);
356
+ v.setAttribute('x2', x);
357
+ v.setAttribute('y1', '0');
358
+ v.setAttribute('y2', '640');
359
+
360
+ // Calculate real coordinates using inverse transformation
361
+ const matrix = {
362
+ "a": 54.41119315973572,
363
+ "c": 0,
364
+ "e": 308.0295375048581,
365
+ "b": 0,
366
+ "d": -54.41119315973572,
367
+ "f": 322.1764477263894
368
+ };
369
+ // Manually invert and apply the affine transform
370
+ // Since we only use translate and scale, we can directly compute:
371
+ // x' = (x - tx) / sx
372
+ // y' = (y - ty) / sy
373
+ const sx = matrix.a;
374
+ const sy = matrix.d;
375
+ const tx = matrix.e;
376
+ const ty = matrix.f;
377
+ const realPoint = {
378
+ x: (x - tx) / sx,
379
+ y: (y - ty) / sy // Flip y back since we used negative scale
380
+ }
381
+
382
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
383
+ coords.setAttribute('x', (x + 5).toString());
384
+ coords.setAttribute('y', (y - 5).toString());
385
+ });
386
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
387
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
388
+ });
389
+ ]]>
390
+ </script>
391
+ </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/example32.json"
4
+ import "tests/fixtures/matcher"
5
+
6
+ test("example31 -> VCC net labels should be at a corner whenever feasible", () => {
7
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
8
+
9
+ solver.solve()
10
+
11
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
12
+ })
@@ -0,0 +1,70 @@
1
+ import { test, expect } from "bun:test"
2
+ import { MspConnectionPairSolver } from "lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver"
3
+ import { NetLabelPlacementSolver } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
4
+ import { visualizeInputProblem } from "lib/solvers/SchematicTracePipelineSolver/visualizeInputProblem"
5
+ import type { InputProblem } from "lib/types/InputProblem"
6
+
7
+ const createInputProblem = (): InputProblem => ({
8
+ chips: [
9
+ {
10
+ chipId: "schematic_component_0",
11
+ center: { x: 0, y: 0 },
12
+ width: 1,
13
+ height: 1,
14
+ sectionId: "section-a",
15
+ pins: [{ pinId: "U1.1", x: 0.5, y: 0, _facingDirection: "x+" }],
16
+ },
17
+ {
18
+ chipId: "schematic_component_1",
19
+ center: { x: 2, y: 0 },
20
+ width: 1,
21
+ height: 1,
22
+ sectionId: "section-b",
23
+ pins: [{ pinId: "U2.1", x: 1.5, y: 0, _facingDirection: "x-" }],
24
+ },
25
+ ],
26
+ directConnections: [{ pinIds: ["U1.1", "U2.1"], netId: "SIG" }],
27
+ netConnections: [],
28
+ availableNetLabelOrientations: {},
29
+ maxMspPairDistance: 10,
30
+ })
31
+
32
+ test("MspConnectionPairSolver skips pairs between different schematic sections", () => {
33
+ const solver = new MspConnectionPairSolver({
34
+ inputProblem: createInputProblem(),
35
+ })
36
+
37
+ solver.solve()
38
+
39
+ expect(solver.mspConnectionPairs).toHaveLength(0)
40
+ })
41
+
42
+ test("cross-section skipped trace is replaced by port net labels", () => {
43
+ const inputProblem = createInputProblem()
44
+ const solver = new NetLabelPlacementSolver({
45
+ inputProblem,
46
+ inputTraceMap: {},
47
+ })
48
+
49
+ solver.solve()
50
+
51
+ expect(solver.netLabelPlacements).toHaveLength(2)
52
+ expect(solver.netLabelPlacements.map((p) => p.pinIds[0]).sort()).toEqual([
53
+ "U1.1",
54
+ "U2.1",
55
+ ])
56
+ expect(solver.netLabelPlacements.every((p) => p.netId === "SIG")).toBe(true)
57
+ })
58
+
59
+ test("cross-section input connections are not visualized as future traces", () => {
60
+ const directConnectionProblem = createInputProblem()
61
+ expect(visualizeInputProblem(directConnectionProblem).lines).toHaveLength(0)
62
+
63
+ const netConnectionProblem = createInputProblem()
64
+ netConnectionProblem.directConnections = []
65
+ netConnectionProblem.netConnections = [
66
+ { netId: "SIG", pinIds: ["U1.1", "U2.1"] },
67
+ ]
68
+
69
+ expect(visualizeInputProblem(netConnectionProblem).lines).toHaveLength(0)
70
+ })