@tscircuit/schematic-trace-solver 0.0.90 → 0.0.92

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.
Files changed (33) hide show
  1. package/dist/index.js +121 -2
  2. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +20 -14
  3. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/calculateDirectShortPath.ts +161 -0
  4. package/lib/solvers/SchematicTracePipelineSolver/correctPinsInsideChip.ts +19 -0
  5. package/package.json +1 -1
  6. package/site/bug-reports/bug-report-20260707T230831Z.page.tsx +4 -0
  7. package/site/bug-reports/bug-report-20260708T053736Z.page.tsx +4 -0
  8. package/site/bug-reports/bug-report-20260708T055430Z.page.tsx +4 -0
  9. package/site/bug-reports/bug-report-20260708T095725Z.page.tsx +4 -0
  10. package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +88 -0
  11. package/tests/bug-reports/bug-report-20260707T230831Z/bug-report-20260707T230831Z.json +347 -0
  12. package/tests/bug-reports/bug-report-20260707T230831Z/bug-report-20260707T230831Z.test.ts +12 -0
  13. package/tests/bug-reports/bug-report-20260708T053736Z/__snapshots__/bug-report-20260708T053736Z.snap.svg +52 -0
  14. package/tests/bug-reports/bug-report-20260708T053736Z/bug-report-20260708T053736Z.json +59 -0
  15. package/tests/bug-reports/bug-report-20260708T053736Z/bug-report-20260708T053736Z.test.ts +12 -0
  16. package/tests/bug-reports/bug-report-20260708T055430Z/__snapshots__/bug-report-20260708T055430Z.snap.svg +88 -0
  17. package/tests/bug-reports/bug-report-20260708T055430Z/bug-report-20260708T055430Z.json +263 -0
  18. package/tests/bug-reports/bug-report-20260708T055430Z/bug-report-20260708T055430Z.test.ts +12 -0
  19. package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +87 -0
  20. package/tests/bug-reports/bug-report-20260708T095725Z/bug-report-20260708T095725Z.json +277 -0
  21. package/tests/bug-reports/bug-report-20260708T095725Z/bug-report-20260708T095725Z.test.ts +12 -0
  22. package/tests/repros/__snapshots__/repro-missing-trace-netlabel.snap.svg +62 -0
  23. package/tests/repros/__snapshots__/repro-netlabel-overlap-trace.snap.svg +60 -0
  24. package/tests/repros/__snapshots__/repro-rectifier-trace-overlap.snap.svg +58 -0
  25. package/tests/repros/__snapshots__/small-variant-resistor-facing-direction.snap.svg +86 -0
  26. package/tests/repros/assets/repro-missing-trace-netlabel.input.json +155 -0
  27. package/tests/repros/assets/repro-netlabel-overlap-trace.input.json +115 -0
  28. package/tests/repros/assets/repro-rectifier-trace-overlap.input.json +137 -0
  29. package/tests/repros/assets/small-variant-resistor-facing-direction.input.json +297 -0
  30. package/tests/repros/repro-missing-trace-netlabel.test.ts +14 -0
  31. package/tests/repros/repro-netlabel-overlap-trace.test.ts +14 -0
  32. package/tests/repros/repro-rectifier-trace-overlap.test.ts +14 -0
  33. package/tests/repros/small-variant-resistor-facing-direction.test.ts +35 -0
package/dist/index.js CHANGED
@@ -577,7 +577,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
577
577
  import "graphics-debug";
578
578
 
579
579
  // lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts
580
- import { calculateElbow } from "calculate-elbow";
580
+ import { calculateElbow as calculateElbow2 } from "calculate-elbow";
581
581
 
582
582
  // lib/solvers/GuidelinesSolver/getInputChipBounds.ts
583
583
  function getInputChipBounds(chip) {
@@ -846,6 +846,111 @@ function getRectBounds(center, w, h) {
846
846
  };
847
847
  }
848
848
 
849
+ // lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/calculateDirectShortPath.ts
850
+ import { calculateElbow } from "calculate-elbow";
851
+ var MAX_SHORT_TRACE_DISTANCE = 0.15;
852
+ var SHORT_TRACE_OVERSHOOT = MAX_SHORT_TRACE_DISTANCE / 7.5;
853
+ var FALLBACK_ELBOW_MAX_OVERSHOOT = 0.2;
854
+ function segmentDirection(from, to) {
855
+ if (to.x > from.x) return "x+";
856
+ if (to.x < from.x) return "x-";
857
+ if (to.y > from.y) return "y+";
858
+ if (to.y < from.y) return "y-";
859
+ return null;
860
+ }
861
+ function pathMatchesPinDirections({
862
+ path,
863
+ pin1,
864
+ pin2
865
+ }) {
866
+ const firstDirection = segmentDirection(path[0], path[1]);
867
+ const lastDirection = segmentDirection(
868
+ path[path.length - 1],
869
+ path[path.length - 2]
870
+ );
871
+ return firstDirection === pin1._facingDirection && lastDirection === pin2._facingDirection;
872
+ }
873
+ function calculateShortOrthogonalRoute(pin1, pin2) {
874
+ if (pin1.x === pin2.x || pin1.y === pin2.y) return null;
875
+ const firstDir = pin1._facingDirection;
876
+ const lastDir = pin2._facingDirection;
877
+ const start = { x: pin1.x, y: pin1.y };
878
+ const end = { x: pin2.x, y: pin2.y };
879
+ let path = null;
880
+ if (firstDir?.startsWith("y") && lastDir?.startsWith("x")) {
881
+ let yOffset = -SHORT_TRACE_OVERSHOOT;
882
+ if (firstDir === "y+") {
883
+ yOffset = SHORT_TRACE_OVERSHOOT;
884
+ }
885
+ const routeY = start.y + yOffset;
886
+ const routeX = (start.x + end.x) / 2;
887
+ path = [
888
+ start,
889
+ { x: start.x, y: routeY },
890
+ { x: routeX, y: routeY },
891
+ { x: routeX, y: end.y },
892
+ end
893
+ ];
894
+ } else if (firstDir?.startsWith("x") && lastDir?.startsWith("y")) {
895
+ let xOffset = -SHORT_TRACE_OVERSHOOT;
896
+ if (firstDir === "x+") {
897
+ xOffset = SHORT_TRACE_OVERSHOOT;
898
+ }
899
+ const routeX = start.x + xOffset;
900
+ const routeY = (start.y + end.y) / 2;
901
+ path = [
902
+ start,
903
+ { x: routeX, y: start.y },
904
+ { x: routeX, y: routeY },
905
+ { x: end.x, y: routeY },
906
+ end
907
+ ];
908
+ }
909
+ if (!path) return null;
910
+ if (pathMatchesPinDirections({ path, pin1, pin2 })) {
911
+ return path;
912
+ }
913
+ return null;
914
+ }
915
+ function calculateDirectShortPath(pin1, pin2) {
916
+ const routingDistance = Math.abs(pin1.x - pin2.x) + Math.abs(pin1.y - pin2.y);
917
+ if (routingDistance > MAX_SHORT_TRACE_DISTANCE) return null;
918
+ const start = { x: pin1.x, y: pin1.y };
919
+ const end = { x: pin2.x, y: pin2.y };
920
+ const orthogonalRoute = calculateShortOrthogonalRoute(pin1, pin2);
921
+ if (orthogonalRoute) return orthogonalRoute;
922
+ let candidatePaths = [];
923
+ if (pin1.x !== pin2.x && pin1.y !== pin2.y) {
924
+ candidatePaths = [
925
+ [start, { x: pin2.x, y: pin1.y }, end],
926
+ [start, { x: pin1.x, y: pin2.y }, end]
927
+ ];
928
+ } else {
929
+ candidatePaths = [[start, end]];
930
+ }
931
+ for (const path of candidatePaths) {
932
+ if (pathMatchesPinDirections({ path, pin1, pin2 })) return path;
933
+ }
934
+ return calculateElbow(
935
+ {
936
+ x: pin1.x,
937
+ y: pin1.y,
938
+ facingDirection: pin1._facingDirection
939
+ },
940
+ {
941
+ x: pin2.x,
942
+ y: pin2.y,
943
+ facingDirection: pin2._facingDirection
944
+ },
945
+ {
946
+ overshoot: Math.min(
947
+ FALLBACK_ELBOW_MAX_OVERSHOOT,
948
+ Math.max(SHORT_TRACE_OVERSHOOT, routingDistance / 4)
949
+ )
950
+ }
951
+ );
952
+ }
953
+
849
954
  // lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts
850
955
  var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
851
956
  pins;
@@ -885,7 +990,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
885
990
  ) : []
886
991
  );
887
992
  const [pin1, pin2] = this.pins;
888
- this.baseElbow = calculateElbow(
993
+ const directShortPath = calculateDirectShortPath(pin1, pin2);
994
+ this.baseElbow = directShortPath ?? calculateElbow2(
889
995
  {
890
996
  x: pin1.x,
891
997
  y: pin1.y,
@@ -898,6 +1004,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
898
1004
  },
899
1005
  { overshoot: 0.2 }
900
1006
  );
1007
+ this.solvedTracePath = directShortPath;
901
1008
  this.aabb = aabbFromPoints(
902
1009
  { x: pin1.x, y: pin1.y },
903
1010
  { x: pin2.x, y: pin2.y }
@@ -3838,6 +3945,18 @@ var correctPinsInsideChips = (problem) => {
3838
3945
  for (const pin of chip.pins) {
3839
3946
  const isInside = pin.x > bounds.minX && pin.x < bounds.maxX && pin.y > bounds.minY && pin.y < bounds.maxY;
3840
3947
  if (!isInside) continue;
3948
+ if (pin._facingDirection) {
3949
+ if (pin._facingDirection === "x-") {
3950
+ pin.x = bounds.minX;
3951
+ } else if (pin._facingDirection === "x+") {
3952
+ pin.x = bounds.maxX;
3953
+ } else if (pin._facingDirection === "y-") {
3954
+ pin.y = bounds.minY;
3955
+ } else {
3956
+ pin.y = bounds.maxY;
3957
+ }
3958
+ continue;
3959
+ }
3841
3960
  const distLeft = pin.x - bounds.minX;
3842
3961
  const distRight = bounds.maxX - pin.x;
3843
3962
  const distBottom = pin.y - bounds.minY;
@@ -18,6 +18,7 @@ import { pathKey, shiftSegmentOrth } from "./pathOps"
18
18
  import type { FacingDirection } from "lib/utils/dir"
19
19
  import { getDimsForOrientation } from "lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry"
20
20
  import type { RectPadding } from "lib/utils/textBoxBounds"
21
+ import { calculateDirectShortPath } from "./calculateDirectShortPath"
21
22
 
22
23
  type PathKey = string
23
24
 
@@ -80,21 +81,26 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
80
81
  : [],
81
82
  )
82
83
 
83
- // Build initial elbow path
84
84
  const [pin1, pin2] = this.pins
85
- this.baseElbow = calculateElbow(
86
- {
87
- x: pin1.x,
88
- y: pin1.y,
89
- facingDirection: pin1._facingDirection!,
90
- },
91
- {
92
- x: pin2.x,
93
- y: pin2.y,
94
- facingDirection: pin2._facingDirection!,
95
- },
96
- { overshoot: 0.2 },
97
- )
85
+ const directShortPath = calculateDirectShortPath(pin1, pin2)
86
+
87
+ // Build initial elbow path
88
+ this.baseElbow =
89
+ directShortPath ??
90
+ calculateElbow(
91
+ {
92
+ x: pin1.x,
93
+ y: pin1.y,
94
+ facingDirection: pin1._facingDirection!,
95
+ },
96
+ {
97
+ x: pin2.x,
98
+ y: pin2.y,
99
+ facingDirection: pin2._facingDirection!,
100
+ },
101
+ { overshoot: 0.2 },
102
+ )
103
+ this.solvedTracePath = directShortPath
98
104
 
99
105
  // Bounds defined by PA and PB
100
106
  this.aabb = aabbFromPoints(
@@ -0,0 +1,161 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import type { MspConnectionPair } from "lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver"
3
+ import type { FacingDirection } from "lib/utils/dir"
4
+ import { calculateElbow } from "calculate-elbow"
5
+
6
+ const MAX_SHORT_TRACE_DISTANCE = 0.15
7
+ const SHORT_TRACE_OVERSHOOT = MAX_SHORT_TRACE_DISTANCE / 7.5
8
+ const FALLBACK_ELBOW_MAX_OVERSHOOT = 0.2
9
+
10
+ export function segmentDirection(
11
+ from: Point,
12
+ to: Point,
13
+ ): FacingDirection | null {
14
+ if (to.x > from.x) return "x+"
15
+ if (to.x < from.x) return "x-"
16
+ if (to.y > from.y) return "y+"
17
+ if (to.y < from.y) return "y-"
18
+ return null
19
+ }
20
+
21
+ export function pathMatchesPinDirections({
22
+ path,
23
+ pin1,
24
+ pin2,
25
+ }: {
26
+ path: Point[]
27
+ pin1: MspConnectionPair["pins"][number]
28
+ pin2: MspConnectionPair["pins"][number]
29
+ }): boolean {
30
+ const firstDirection = segmentDirection(path[0]!, path[1]!)
31
+ const lastDirection = segmentDirection(
32
+ path[path.length - 1]!,
33
+ path[path.length - 2]!,
34
+ )
35
+
36
+ return (
37
+ firstDirection === pin1._facingDirection &&
38
+ lastDirection === pin2._facingDirection
39
+ )
40
+ }
41
+
42
+ /**
43
+ * Calculates a short orthogonal (perpendicular) route when the source and destination pins
44
+ * are oriented at a 90-degree angle to one another (e.g., one faces X and the other faces Y).
45
+ * It creates a minimal step-out to avoid overlapping pin bodies.
46
+ */
47
+ export function calculateShortOrthogonalRoute(
48
+ pin1: MspConnectionPair["pins"][number],
49
+ pin2: MspConnectionPair["pins"][number],
50
+ ): Point[] | null {
51
+ // If pins share an axis, an orthogonal 3-segment route is unnecessary
52
+ if (pin1.x === pin2.x || pin1.y === pin2.y) return null
53
+
54
+ const firstDir = pin1._facingDirection
55
+ const lastDir = pin2._facingDirection
56
+
57
+ const start = { x: pin1.x, y: pin1.y }
58
+ const end = { x: pin2.x, y: pin2.y }
59
+
60
+ let path: Point[] | null = null
61
+
62
+ // Handle case where pin1 faces vertically and pin2 faces horizontally
63
+ if (firstDir?.startsWith("y") && lastDir?.startsWith("x")) {
64
+ let yOffset = -SHORT_TRACE_OVERSHOOT
65
+ if (firstDir === "y+") {
66
+ yOffset = SHORT_TRACE_OVERSHOOT
67
+ }
68
+ const routeY = start.y + yOffset
69
+ const routeX = (start.x + end.x) / 2
70
+ path = [
71
+ start,
72
+ { x: start.x, y: routeY },
73
+ { x: routeX, y: routeY },
74
+ { x: routeX, y: end.y },
75
+ end,
76
+ ]
77
+ }
78
+ // Handle case where pin1 faces horizontally and pin2 faces vertically
79
+ else if (firstDir?.startsWith("x") && lastDir?.startsWith("y")) {
80
+ let xOffset = -SHORT_TRACE_OVERSHOOT
81
+ if (firstDir === "x+") {
82
+ xOffset = SHORT_TRACE_OVERSHOOT
83
+ }
84
+ const routeX = start.x + xOffset
85
+ const routeY = (start.y + end.y) / 2
86
+ path = [
87
+ start,
88
+ { x: routeX, y: start.y },
89
+ { x: routeX, y: routeY },
90
+ { x: end.x, y: routeY },
91
+ end,
92
+ ]
93
+ }
94
+
95
+ if (!path) return null
96
+
97
+ if (pathMatchesPinDirections({ path, pin1, pin2 })) {
98
+ return path
99
+ }
100
+ return null
101
+ }
102
+
103
+ /**
104
+ * Attempts to calculate a direct route between two pins if they are very close together.
105
+ * This prevents complex routing logic from taking over for trivial connections.
106
+ */
107
+ export function calculateDirectShortPath(
108
+ pin1: MspConnectionPair["pins"][number],
109
+ pin2: MspConnectionPair["pins"][number],
110
+ ): Point[] | null {
111
+ const routingDistance = Math.abs(pin1.x - pin2.x) + Math.abs(pin1.y - pin2.y)
112
+
113
+ // If the distance is too large, fallback to the standard complex routing solver
114
+ if (routingDistance > MAX_SHORT_TRACE_DISTANCE) return null
115
+
116
+ const start = { x: pin1.x, y: pin1.y }
117
+ const end = { x: pin2.x, y: pin2.y }
118
+
119
+ // First, try a simple orthogonal route if the pins are facing perpendicular directions
120
+ const orthogonalRoute = calculateShortOrthogonalRoute(pin1, pin2)
121
+ if (orthogonalRoute) return orthogonalRoute
122
+
123
+ let candidatePaths: Point[][] = []
124
+
125
+ // If the pins are completely offset (neither perfectly aligned horizontally nor vertically),
126
+ // we evaluate standard two-segment L-shaped routes.
127
+ if (pin1.x !== pin2.x && pin1.y !== pin2.y) {
128
+ candidatePaths = [
129
+ [start, { x: pin2.x, y: pin1.y }, end],
130
+ [start, { x: pin1.x, y: pin2.y }, end],
131
+ ]
132
+ } else {
133
+ // If they are perfectly aligned, try a straight line
134
+ candidatePaths = [[start, end]]
135
+ }
136
+
137
+ // Return the first candidate that matches the facing direction requirements of the pins
138
+ for (const path of candidatePaths) {
139
+ if (pathMatchesPinDirections({ path, pin1, pin2 })) return path
140
+ }
141
+
142
+ // If simple paths fail, compute a slightly overshoot-based elbow routing as a final short-trace fallback
143
+ return calculateElbow(
144
+ {
145
+ x: pin1.x,
146
+ y: pin1.y,
147
+ facingDirection: pin1._facingDirection!,
148
+ },
149
+ {
150
+ x: pin2.x,
151
+ y: pin2.y,
152
+ facingDirection: pin2._facingDirection!,
153
+ },
154
+ {
155
+ overshoot: Math.min(
156
+ FALLBACK_ELBOW_MAX_OVERSHOOT,
157
+ Math.max(SHORT_TRACE_OVERSHOOT, routingDistance / 4),
158
+ ),
159
+ },
160
+ )
161
+ }
@@ -13,6 +13,25 @@ export const correctPinsInsideChips = (problem: InputProblem) => {
13
13
 
14
14
  if (!isInside) continue
15
15
 
16
+ // When the pin already knows which way it faces (e.g. the consumer set it
17
+ // from the schematic symbol), snap it to the edge along that direction and
18
+ // keep the facing. A pin can end up inside the box when the box was
19
+ // expanded to include the component's reference-designator text; snapping
20
+ // to the nearest edge would move it to the wrong side (e.g. a horizontal
21
+ // resistor whose wide ref text makes the bottom edge the closest one).
22
+ if (pin._facingDirection) {
23
+ if (pin._facingDirection === "x-") {
24
+ pin.x = bounds.minX
25
+ } else if (pin._facingDirection === "x+") {
26
+ pin.x = bounds.maxX
27
+ } else if (pin._facingDirection === "y-") {
28
+ pin.y = bounds.minY
29
+ } else {
30
+ pin.y = bounds.maxY
31
+ }
32
+ continue
33
+ }
34
+
16
35
  const distLeft = pin.x - bounds.minX
17
36
  const distRight = bounds.maxX - pin.x
18
37
  const distBottom = pin.y - bounds.minY
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.90",
4
+ "version": "0.0.92",
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/bug-reports/bug-report-20260707T230831Z/bug-report-20260707T230831Z.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/bug-reports/bug-report-20260708T053736Z/bug-report-20260708T053736Z.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/bug-reports/bug-report-20260708T055430Z/bug-report-20260708T055430Z.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/bug-reports/bug-report-20260708T095725Z/bug-report-20260708T095725Z.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,88 @@
1
+ <svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="-0.6,3.1 -0.5279125,3.10262455" data-type="line" data-label="" points="312.3309111235327,139.50628261598658 316.84393515930685,139.34197316936837" fill="none" stroke="hsl(232, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.6,3.1 0.5279125,3.0973754500000004" data-type="line" data-label="" points="387.4566797093348,139.50628261598658 382.94365567356067,139.67059206260478" fill="none" stroke="hsl(0, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-1.7999999999999998,0.975 -4.5,0.030000000000000027" data-type="line" data-label="" points="237.20514253773058,272.54149782001116 68.17216321967584,331.70304058133036" fill="none" stroke="hsl(296, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-1.7999999999999998,0.975 -1.7999999999999998,0.32499999999999996" data-type="line" data-label="" points="237.20514253773058,272.54149782001116 237.20514253773058,313.23462247065396" fill="none" stroke="hsl(16, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-1.7999999999999998,0.975 1.55,1.1" data-type="line" data-label="" points="237.20514253773058,272.54149782001116 446.9312465064282,264.7158969256568" fill="none" stroke="hsl(240, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,0.975 3.4,0.030000000000000027" data-type="line" data-label="" points="462.58244829513694,272.54149782001116 562.7501397428731,331.70304058133036" fill="none" stroke="hsl(160, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,0.975 2.25,-0.04999999999999999" data-type="line" data-label="" points="462.58244829513694,272.54149782001116 490.7546115148127,336.71142515371713" fill="none" stroke="hsl(160, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,0.32500000000000007 1.55,0.5" data-type="line" data-label="" points="462.58244829513694,313.23462247065396 446.9312465064282,302.2787812185578" fill="none" stroke="hsl(24, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,-0.32499999999999996 2.25,-0.6499999999999999" data-type="line" data-label="" points="462.58244829513694,353.9277471212968 490.7546115148127,374.2743094466182" fill="none" stroke="hsl(112, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,-0.32499999999999996 2.25,-1.7999999999999998" data-type="line" data-label="" points="462.58244829513694,353.9277471212968 490.7546115148127,446.26983767467857" fill="none" stroke="hsl(112, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-1.7999999999999998,0.32499999999999996 -1.7999999999999998,0.975" data-type="line" data-label="" points="237.20514253773058,313.23462247065396 237.20514253773058,272.54149782001116" fill="none" stroke="hsl(27, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,0.32499999999999996 -4.5,0.030000000000000027" data-type="line" data-label="" points="237.20514253773058,313.23462247065396 68.17216321967584,331.70304058133036" fill="none" stroke="hsl(27, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,0.32499999999999996 1.55,1.1" data-type="line" data-label="" points="237.20514253773058,313.23462247065396 446.9312465064282,264.7158969256568" fill="none" stroke="hsl(27, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,0.975 -4.5,0.030000000000000027" data-type="line" data-label="" points="237.20514253773058,272.54149782001116 68.17216321967584,331.70304058133036" fill="none" stroke="hsl(27, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,0.975 1.55,1.1" data-type="line" data-label="" points="237.20514253773058,272.54149782001116 446.9312465064282,264.7158969256568" fill="none" stroke="hsl(27, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-4.5,0.030000000000000027 1.55,1.1" data-type="line" data-label="" points="68.17216321967584,331.70304058133036 446.9312465064282,264.7158969256568" fill="none" stroke="hsl(27, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.32500000000000007 1.7999999999999998,-0.975" data-type="line" data-label="" points="237.20514253773058,353.9277471212968 462.58244829513694,394.6208717719396" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.32500000000000007 -1.7999999999999998,-0.975" data-type="line" data-label="" points="237.20514253773058,353.9277471212968 237.20514253773058,394.6208717719396" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.32500000000000007 -4.5,-0.73" data-type="line" data-label="" points="237.20514253773058,353.9277471212968 68.17216321967584,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.32500000000000007 3.4,-0.73" data-type="line" data-label="" points="237.20514253773058,353.9277471212968 562.7501397428731,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.32500000000000007 2.25,-2.4000000000000004" data-type="line" data-label="" points="237.20514253773058,353.9277471212968 490.7546115148127,483.8327219675797" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,-0.975 -1.7999999999999998,-0.975" data-type="line" data-label="" points="462.58244829513694,394.6208717719396 237.20514253773058,394.6208717719396" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,-0.975 -4.5,-0.73" data-type="line" data-label="" points="462.58244829513694,394.6208717719396 68.17216321967584,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,-0.975 3.4,-0.73" data-type="line" data-label="" points="462.58244829513694,394.6208717719396 562.7501397428731,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,-0.975 2.25,-2.4000000000000004" data-type="line" data-label="" points="462.58244829513694,394.6208717719396 490.7546115148127,483.8327219675797" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.975 -4.5,-0.73" data-type="line" data-label="" points="237.20514253773058,394.6208717719396 68.17216321967584,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.975 3.4,-0.73" data-type="line" data-label="" points="237.20514253773058,394.6208717719396 562.7501397428731,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-1.7999999999999998,-0.975 2.25,-2.4000000000000004" data-type="line" data-label="" points="237.20514253773058,394.6208717719396 490.7546115148127,483.8327219675797" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-4.5,-0.73 3.4,-0.73" data-type="line" data-label="" points="68.17216321967584,379.282694019005 562.7501397428731,379.282694019005" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-4.5,-0.73 2.25,-2.4000000000000004" data-type="line" data-label="" points="68.17216321967584,379.282694019005 490.7546115148127,483.8327219675797" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="3.4,-0.73 2.25,-2.4000000000000004" data-type="line" data-label="" points="562.7501397428731,379.282694019005 490.7546115148127,483.8327219675797" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,0.32500000000000007 1.55,0.5" data-type="line" data-label="" points="462.58244829513694,313.23462247065396 446.9312465064282,302.2787812185578" fill="none" stroke="hsl(31, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,0.975 3.4,0.030000000000000027" data-type="line" data-label="" points="462.58244829513694,272.54149782001116 562.7501397428731,331.70304058133036" fill="none" stroke="hsl(64, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,0.975 2.25,-0.04999999999999999" data-type="line" data-label="" points="462.58244829513694,272.54149782001116 490.7546115148127,336.71142515371713" fill="none" stroke="hsl(64, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="3.4,0.030000000000000027 2.25,-0.04999999999999999" data-type="line" data-label="" points="562.7501397428731,331.70304058133036 490.7546115148127,336.71142515371713" fill="none" stroke="hsl(64, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-0.6,3.1 -0.6,3.12 -0.5639562499999999,3.12 -0.5639562499999999,3.10262455 -0.5279125,3.10262455" data-type="line" data-label="" points="312.3309111235327,139.50628261598658 312.3309111235327,138.25418647288987 314.5874231414198,138.25418647288987 314.5874231414198,139.34197316936837 316.84393515930685,139.34197316936837" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0.6,3.1 0.6,3.12 0.5639562499999999,3.12 0.5639562499999999,3.0973754500000004 0.5279125,3.0973754500000004" data-type="line" data-label="" points="387.4566797093348,139.50628261598658 387.4566797093348,138.25418647288987 385.20016769144775,138.25418647288987 385.20016769144775,139.67059206260478 382.94365567356067,139.67059206260478" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-1.7999999999999998,0.975 -1.9999999999999998,0.975 -1.9999999999999998,0.32499999999999996 -1.7999999999999998,0.32499999999999996" data-type="line" data-label="" points="237.20514253773058,272.54149782001116 224.68418110676356,272.54149782001116 224.68418110676356,313.23462247065396 237.20514253773058,313.23462247065396" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.25,-0.04999999999999999 2.25,0.23000000000000026 3.4,0.23000000000000026 3.4,0.030000000000000082" data-type="line" data-label="" points="490.7546115148127,336.71142515371713 490.7546115148127,319.1820791503633 562.7501397428731,319.1820791503633 562.7501397428731,331.70304058133036" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.25,-1.7999999999999998 2.25,-0.6499999999999999" data-type="line" data-label="" points="490.7546115148127,446.26983767467857 490.7546115148127,374.2743094466182" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,-0.975 3.4,-0.975 3.4,-0.73" data-type="line" data-label="" points="462.58244829513694,394.6208717719396 562.7501397428731,394.6208717719396 562.7501397428731,379.282694019005" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.25,-2.4000000000000004 2.25,-2.6000000000000005 3.0900000000000003,-2.6000000000000005 3.0900000000000003,-0.975 1.7999999999999998,-0.975" data-type="line" data-label="" points="490.7546115148127,483.8327219675797 490.7546115148127,496.35368339854665 543.3426495248742,496.35368339854665 543.3426495248742,394.6208717719396 462.58244829513694,394.6208717719396" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-1.7999999999999998,-0.975 -1.9999999999999998,-0.975 -1.9999999999999998,-0.32500000000000007 -1.7999999999999998,-0.32500000000000007" data-type="line" data-label="" points="237.20514253773058,394.6208717719396 224.68418110676356,394.6208717719396 224.68418110676356,353.9277471212968 237.20514253773058,353.9277471212968" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-4.5,-0.73 -4.5,-0.9750000000000001 -1.7999999999999998,-0.9750000000000001" data-type="line" data-label="" points="68.17216321967584,379.282694019005 68.17216321967584,394.6208717719396 237.20514253773058,394.6208717719396" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-1.9999999999999998,0.975 -2.2899999999999996,0.975 -2.2899999999999996,0.976" data-type="line" data-label="" points="224.68418110676356,272.54149782001116 206.5287870318614,272.54149782001116 206.5287870318614,272.47889301285636" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0" x="237.20514253773058" y="139.5062826159866" width="225.37730575740636" height="388.14980435997757" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="0" data-y="3.1" x="316.84393515930685" y="112.34391302403574" width="66.09972051425382" height="54.32473918390167" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="-4.4275" data-y="-0.35" x="40" y="331.70304058133036" width="65.42202347680268" height="47.579653437674665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="3.4725" data-y="-0.35" x="534.5779765231973" y="331.70304058133036" width="65.42202347680268" height="47.579653437674665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="schematic_component_4" data-x="2.4050000000000002" data-y="-0.35" x="462.58244829513694" y="336.7114251537172" width="75.75181665735045" height="37.56288429290106" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="schematic_component_5" data-x="2.345" data-y="-2.1" x="462.582448295137" y="446.26983767467857" width="68.2392397987702" height="37.56288429290112" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="schematic_component_6" data-x="1.705" data-y="0.8" x="418.75908328675234" y="264.7158969256568" width="75.7518166573505" height="37.562884292901" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="TPS63802DLAR" data-x="2.2199999999999998" data-y="3.0500000000000003" x="443.8010061486864" y="137.00209032979316" width="90.1509223029625" height="11.268865287870312" fill="rgba(160, 0, 220, 0.14)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="U1" data-x="1.62" data-y="2.8150000000000004" x="440.0447177193963" y="149.52305176076018" width="22.537730575740625" height="15.65120178870876" fill="rgba(160, 0, 220, 0.14)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: VIN
2
+ globalConnNetId: connectivity_net2" data-x="-2.2899999999999996" data-y="1.186" x="191.503633314701" y="246.18487400782558" width="30.050307434320814" height="26.294019005030748" fill="#ef444466" stroke="#ef4444" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: VIN
3
+ globalConnNetId: connectivity_net2" data-x="-4.5" data-y="0.24100000000000002" x="53.147009502515374" y="305.34641676914475" width="30.050307434320928" height="26.294019005030748" fill="#ef444466" stroke="#ef4444" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: VIN
4
+ globalConnNetId: connectivity_net2" data-x="1.55" data-y="1.311" x="440.67076579094464" y="238.3592731134712" width="12.520961430967077" height="26.294019005030748" fill="#ef444466" stroke="#ef4444" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: GND
5
+ globalConnNetId: connectivity_net6" data-x="-4.5" data-y="-1.185" x="53.147009502515374" y="394.6208717719396" width="30.050307434320928" height="26.294019005030748" fill="#00000066" stroke="#000000" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: GND
6
+ globalConnNetId: connectivity_net6" data-x="2.25" data-y="-2.8100000000000005" x="475.72945779765223" y="496.35368339854665" width="30.050307434320928" height="26.294019005030805" fill="#00000066" stroke="#000000" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: U1.FB to R2.pin1
7
+ globalConnNetId: connectivity_net5" data-x="2.026" data-y="-0.32499999999999996" x="462.64505310229174" y="347.6672664058133" width="28.172163219675838" height="12.52096143096702" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: U1.FB to R2.pin1
8
+ globalConnNetId: connectivity_net5" data-x="2.475" data-y="-1.2249999999999999" x="490.7546115148128" y="404.01159284516484" width="28.17216321967578" height="12.520961430967077" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: PG
9
+ globalConnNetId: connectivity_net4" data-x="1.9809999999999997" data-y="0.32500000000000007" x="462.64505310229174" y="306.9741417551704" width="22.537730575740625" height="12.52096143096702" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: PG
10
+ globalConnNetId: connectivity_net4" data-x="1.55" data-y="0.319" x="440.67076579094464" y="302.34138602571267" width="12.520961430967077" height="22.537730575740625" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: VOUT
11
+ globalConnNetId: connectivity_net3" data-x="2.0109999999999997" data-y="0.975" x="462.64505310229174" y="266.2810171045277" width="26.294019005030748" height="12.52096143096702" fill="#ef444466" stroke="#ef4444" stroke-width="0.015973214285714285"/></g><g><rect data-type="rect" data-label="netId: VOUT
12
+ globalConnNetId: connectivity_net3" data-x="2.825" data-y="0.4400000000000003" x="507.97093348239247" y="292.8880601453326" width="37.562884292901" height="26.29401900503069" fill="#ef444466" stroke="#ef4444" stroke-width="0.015973214285714285"/></g><g><circle data-type="point" data-label="U1.1
13
+ x-" data-x="-1.7999999999999998" data-y="0.32499999999999996" cx="237.20514253773058" cy="313.23462247065396" r="3" fill="hsl(319, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.2
14
+ x-" data-x="-1.7999999999999998" data-y="-0.32500000000000007" cx="237.20514253773058" cy="353.9277471212968" r="3" fill="hsl(320, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.3
15
+ x+" data-x="1.7999999999999998" data-y="-0.975" cx="462.58244829513694" cy="394.6208717719396" r="3" fill="hsl(321, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.4
16
+ x+" data-x="1.7999999999999998" data-y="-0.32499999999999996" cx="462.58244829513694" cy="353.9277471212968" r="3" fill="hsl(322, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.5
17
+ x+" data-x="1.7999999999999998" data-y="0.32500000000000007" cx="462.58244829513694" cy="313.23462247065396" r="3" fill="hsl(323, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.6
18
+ x+" data-x="1.7999999999999998" data-y="0.975" cx="462.58244829513694" cy="272.54149782001116" r="3" fill="hsl(324, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.7
19
+ y+" data-x="0.6" data-y="3.1" cx="387.4566797093348" cy="139.50628261598658" r="3" fill="hsl(325, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.8
20
+ x-" data-x="-1.7999999999999998" data-y="-0.975" cx="237.20514253773058" cy="394.6208717719396" r="3" fill="hsl(326, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.9
21
+ y+" data-x="-0.6" data-y="3.1" cx="312.3309111235327" cy="139.50628261598658" r="3" fill="hsl(327, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.10
22
+ x-" data-x="-1.7999999999999998" data-y="0.975" cx="237.20514253773058" cy="272.54149782001116" r="3" fill="hsl(217, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="L1.1
23
+ x-" data-x="-0.5279125" data-y="3.10262455" cx="316.84393515930685" cy="139.34197316936837" r="3" fill="hsl(40, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="L1.2
24
+ x+" data-x="0.5279125" data-y="3.0973754500000004" cx="382.94365567356067" cy="139.67059206260478" r="3" fill="hsl(41, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="C1.1
25
+ y+" data-x="-4.5" data-y="0.030000000000000027" cx="68.17216321967584" cy="331.70304058133036" r="3" fill="hsl(121, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="C1.2
26
+ y-" data-x="-4.5" data-y="-0.73" cx="68.17216321967584" cy="379.282694019005" r="3" fill="hsl(122, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="C2.1
27
+ y+" data-x="3.4" data-y="0.030000000000000027" cx="562.7501397428731" cy="331.70304058133036" r="3" fill="hsl(2, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="C2.2
28
+ y-" data-x="3.4" data-y="-0.73" cx="562.7501397428731" cy="379.282694019005" r="3" fill="hsl(3, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R1.1
29
+ y+" data-x="2.25" data-y="-0.04999999999999999" cx="490.7546115148127" cy="336.71142515371713" r="3" fill="hsl(226, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R1.2
30
+ y-" data-x="2.25" data-y="-0.6499999999999999" cx="490.7546115148127" cy="374.2743094466182" r="3" fill="hsl(227, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.1
31
+ y+" data-x="2.25" data-y="-1.7999999999999998" cx="490.7546115148127" cy="446.26983767467857" r="3" fill="hsl(107, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.2
32
+ y-" data-x="2.25" data-y="-2.4000000000000004" cx="490.7546115148127" cy="483.8327219675797" r="3" fill="hsl(108, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.1
33
+ y+" data-x="1.55" data-y="1.1" cx="446.9312465064282" cy="264.7158969256568" r="3" fill="hsl(348, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.2
34
+ y-" data-x="1.55" data-y="0.5" cx="446.9312465064282" cy="302.2787812185578" r="3" fill="hsl(349, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
35
+ orientation: y+" data-x="-2.2899999999999996" data-y="0.976" cx="206.5287870318614" cy="272.47889301285636" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
36
+ orientation: y+" data-x="-4.5" data-y="0.030000000000000027" cx="68.17216321967584" cy="331.70304058133036" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
37
+ orientation: y+" data-x="1.55" data-y="1.1" cx="446.9312465064282" cy="264.7158969256568" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
38
+ orientation: y-" data-x="-4.5" data-y="-0.9750000000000001" cx="68.17216321967584" cy="394.6208717719396" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
39
+ orientation: y-" data-x="2.25" data-y="-2.6000000000000005" cx="490.7546115148127" cy="496.35368339854665" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
40
+ orientation: x+" data-x="1.7999999999999998" data-y="-0.32499999999999996" cx="462.58244829513694" cy="353.9277471212968" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
41
+ orientation: x+" data-x="2.25" data-y="-1.2249999999999999" cx="490.7546115148127" cy="410.2720735606484" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
42
+ orientation: x+" data-x="1.7999999999999998" data-y="0.32500000000000007" cx="462.58244829513694" cy="313.23462247065396" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
43
+ orientation: y-" data-x="1.55" data-y="0.5" cx="446.9312465064282" cy="302.2787812185578" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
44
+ orientation: x+" data-x="1.7999999999999998" data-y="0.975" cx="462.58244829513694" cy="272.54149782001116" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
45
+ orientation: y+" data-x="2.825" data-y="0.23000000000000026" cx="526.752375628843" cy="319.1820791503633" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><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></g><script><![CDATA[
46
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
47
+ const svg = e.currentTarget;
48
+ const rect = svg.getBoundingClientRect();
49
+ const x = e.clientX - rect.left;
50
+ const y = e.clientY - rect.top;
51
+ const crosshair = svg.getElementById('crosshair');
52
+ const h = svg.getElementById('crosshair-h');
53
+ const v = svg.getElementById('crosshair-v');
54
+ const coords = svg.getElementById('coordinates');
55
+
56
+ crosshair.style.display = 'block';
57
+ h.setAttribute('x1', '0');
58
+ h.setAttribute('x2', '640');
59
+ h.setAttribute('y1', y);
60
+ h.setAttribute('y2', y);
61
+ v.setAttribute('x1', x);
62
+ v.setAttribute('x2', x);
63
+ v.setAttribute('y1', '0');
64
+ v.setAttribute('y2', '640');
65
+
66
+ // Calculate real coordinates using inverse transformation
67
+ const matrix = {"a":62.6048071548351,"c":0,"e":349.89379541643376,"b":0,"d":-62.6048071548351,"f":333.5811847959754};
68
+ // Manually invert and apply the affine transform
69
+ // Since we only use translate and scale, we can directly compute:
70
+ // x' = (x - tx) / sx
71
+ // y' = (y - ty) / sy
72
+ const sx = matrix.a;
73
+ const sy = matrix.d;
74
+ const tx = matrix.e;
75
+ const ty = matrix.f;
76
+ const realPoint = {
77
+ x: (x - tx) / sx,
78
+ y: (y - ty) / sy // Flip y back since we used negative scale
79
+ }
80
+
81
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
82
+ coords.setAttribute('x', (x + 5).toString());
83
+ coords.setAttribute('y', (y - 5).toString());
84
+ });
85
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
86
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
87
+ });
88
+ ]]></script></svg>