circuit-json-to-lbrn 0.0.17 → 0.0.18

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
@@ -1,5 +1,5 @@
1
1
  // lib/index.ts
2
- import { LightBurnProject, CutSetting, ShapePath as ShapePath21 } from "lbrnts";
2
+ import { LightBurnProject, CutSetting, ShapePath as ShapePath25 } from "lbrnts";
3
3
  import { cju as cju2 } from "@tscircuit/circuit-json-util";
4
4
 
5
5
  // lib/element-handlers/addPlatedHole/addCirclePlatedHole.ts
@@ -1690,6 +1690,222 @@ var addPcbHole = (hole, ctx) => {
1690
1690
  }
1691
1691
  };
1692
1692
 
1693
+ // lib/element-handlers/addPcbCutout/addCirclePcbCutout.ts
1694
+ import { ShapePath as ShapePath21 } from "lbrnts";
1695
+ var addCirclePcbCutout = (cutout, ctx) => {
1696
+ const {
1697
+ project,
1698
+ throughBoardCutSetting,
1699
+ origin,
1700
+ includeCopper,
1701
+ includeSoldermask,
1702
+ soldermaskMargin,
1703
+ soldermaskCutSetting
1704
+ } = ctx;
1705
+ const centerX = cutout.center.x + origin.x;
1706
+ const centerY = cutout.center.y + origin.y;
1707
+ if (cutout.radius > 0 && includeCopper) {
1708
+ const circlePath = createCirclePath(centerX, centerY, cutout.radius);
1709
+ project.children.push(
1710
+ new ShapePath21({
1711
+ cutIndex: throughBoardCutSetting.index,
1712
+ verts: circlePath.verts,
1713
+ prims: circlePath.prims,
1714
+ isClosed: true
1715
+ })
1716
+ );
1717
+ }
1718
+ if (cutout.radius > 0 && includeSoldermask) {
1719
+ const smRadius = cutout.radius + soldermaskMargin;
1720
+ const outer = createCirclePath(centerX, centerY, smRadius);
1721
+ project.children.push(
1722
+ new ShapePath21({
1723
+ cutIndex: soldermaskCutSetting.index,
1724
+ verts: outer.verts,
1725
+ prims: outer.prims,
1726
+ isClosed: true
1727
+ })
1728
+ );
1729
+ }
1730
+ };
1731
+
1732
+ // lib/element-handlers/addPcbCutout/addRectPcbCutout.ts
1733
+ import { ShapePath as ShapePath22 } from "lbrnts";
1734
+ var addRectPcbCutout = (cutout, ctx) => {
1735
+ const {
1736
+ project,
1737
+ throughBoardCutSetting,
1738
+ origin,
1739
+ includeCopper,
1740
+ includeSoldermask,
1741
+ soldermaskMargin,
1742
+ soldermaskCutSetting
1743
+ } = ctx;
1744
+ const centerX = cutout.center.x + origin.x;
1745
+ const centerY = cutout.center.y + origin.y;
1746
+ if (cutout.width > 0 && cutout.height > 0 && includeCopper) {
1747
+ const rotation = (cutout.rotation ?? 0) * (Math.PI / 180);
1748
+ const rectPath = createRoundedRectPath(
1749
+ centerX,
1750
+ centerY,
1751
+ cutout.width,
1752
+ cutout.height,
1753
+ 0,
1754
+ // no border radius for cutouts
1755
+ 4,
1756
+ // segments
1757
+ rotation
1758
+ );
1759
+ project.children.push(
1760
+ new ShapePath22({
1761
+ cutIndex: throughBoardCutSetting.index,
1762
+ verts: rectPath.verts,
1763
+ prims: rectPath.prims,
1764
+ isClosed: true
1765
+ })
1766
+ );
1767
+ }
1768
+ if (cutout.width > 0 && cutout.height > 0 && includeSoldermask) {
1769
+ const rotation = (cutout.rotation ?? 0) * (Math.PI / 180);
1770
+ const smWidth = cutout.width + 2 * soldermaskMargin;
1771
+ const smHeight = cutout.height + 2 * soldermaskMargin;
1772
+ const rectPath = createRoundedRectPath(
1773
+ centerX,
1774
+ centerY,
1775
+ smWidth,
1776
+ smHeight,
1777
+ 0,
1778
+ // no border radius for cutouts
1779
+ 4,
1780
+ // segments
1781
+ rotation
1782
+ );
1783
+ project.children.push(
1784
+ new ShapePath22({
1785
+ cutIndex: soldermaskCutSetting.index,
1786
+ verts: rectPath.verts,
1787
+ prims: rectPath.prims,
1788
+ isClosed: true
1789
+ })
1790
+ );
1791
+ }
1792
+ };
1793
+
1794
+ // lib/element-handlers/addPcbCutout/addPolygonPcbCutout.ts
1795
+ import { ShapePath as ShapePath23 } from "lbrnts";
1796
+ var addPolygonPcbCutout = (cutout, ctx) => {
1797
+ const {
1798
+ project,
1799
+ throughBoardCutSetting,
1800
+ origin,
1801
+ includeCopper,
1802
+ includeSoldermask,
1803
+ soldermaskCutSetting,
1804
+ soldermaskMargin
1805
+ } = ctx;
1806
+ if (cutout.points.length >= 3 && includeCopper) {
1807
+ const polygonPath = createPolygonPathFromOutline(
1808
+ cutout.points,
1809
+ origin.x,
1810
+ origin.y
1811
+ );
1812
+ project.children.push(
1813
+ new ShapePath23({
1814
+ cutIndex: throughBoardCutSetting.index,
1815
+ verts: polygonPath.verts,
1816
+ prims: polygonPath.prims,
1817
+ isClosed: true
1818
+ })
1819
+ );
1820
+ }
1821
+ if (cutout.points.length >= 3 && includeSoldermask) {
1822
+ const points = soldermaskMargin && soldermaskMargin > 0 ? cutout.points.map((p) => ({
1823
+ x: (p.x ?? 0) + (p.x ?? 0) > 0 ? soldermaskMargin : -soldermaskMargin,
1824
+ y: (p.y ?? 0) + (p.y ?? 0) > 0 ? soldermaskMargin : -soldermaskMargin
1825
+ })) : cutout.points;
1826
+ const polygonPath = createPolygonPathFromOutline(points, origin.x, origin.y);
1827
+ project.children.push(
1828
+ new ShapePath23({
1829
+ cutIndex: soldermaskCutSetting.index,
1830
+ verts: polygonPath.verts,
1831
+ prims: polygonPath.prims,
1832
+ isClosed: true
1833
+ })
1834
+ );
1835
+ }
1836
+ };
1837
+
1838
+ // lib/element-handlers/addPcbCutout/addPathPcbCutout.ts
1839
+ import { ShapePath as ShapePath24 } from "lbrnts";
1840
+ var addPathPcbCutout = (cutout, ctx) => {
1841
+ const {
1842
+ project,
1843
+ throughBoardCutSetting,
1844
+ origin,
1845
+ includeCopper,
1846
+ includeSoldermask,
1847
+ soldermaskMargin,
1848
+ soldermaskCutSetting
1849
+ } = ctx;
1850
+ if (cutout.route.length >= 2 && includeCopper) {
1851
+ const verts = [];
1852
+ const prims = [];
1853
+ for (const point6 of cutout.route) {
1854
+ verts.push({
1855
+ x: point6.x + origin.x,
1856
+ y: point6.y + origin.y
1857
+ });
1858
+ prims.push({ type: 0 });
1859
+ }
1860
+ project.children.push(
1861
+ new ShapePath24({
1862
+ cutIndex: throughBoardCutSetting.index,
1863
+ verts,
1864
+ prims,
1865
+ isClosed: false
1866
+ // Paths are typically not closed
1867
+ })
1868
+ );
1869
+ }
1870
+ if (cutout.route.length >= 2 && includeSoldermask) {
1871
+ const verts = [];
1872
+ const prims = [];
1873
+ for (const point6 of cutout.route) {
1874
+ verts.push({
1875
+ x: point6.x + origin.x,
1876
+ y: point6.y + origin.y
1877
+ });
1878
+ prims.push({ type: 0 });
1879
+ }
1880
+ project.children.push(
1881
+ new ShapePath24({
1882
+ cutIndex: soldermaskCutSetting.index,
1883
+ verts,
1884
+ prims,
1885
+ isClosed: false
1886
+ // Match the same path as the copper cutout
1887
+ })
1888
+ );
1889
+ }
1890
+ };
1891
+
1892
+ // lib/element-handlers/addPcbCutout/index.ts
1893
+ var addPcbCutout = (cutout, ctx) => {
1894
+ switch (cutout.shape) {
1895
+ case "circle":
1896
+ return addCirclePcbCutout(cutout, ctx);
1897
+ case "rect":
1898
+ return addRectPcbCutout(cutout, ctx);
1899
+ case "polygon":
1900
+ return addPolygonPcbCutout(cutout, ctx);
1901
+ case "path":
1902
+ return addPathPcbCutout(cutout, ctx);
1903
+ default:
1904
+ const _exhaustive = cutout;
1905
+ console.warn(`Unknown cutout shape: ${cutout.shape}`);
1906
+ }
1907
+ };
1908
+
1693
1909
  // lib/index.ts
1694
1910
  var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
1695
1911
  const db = cju2(circuitJson);
@@ -1767,6 +1983,9 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
1767
1983
  for (const hole of db.pcb_hole.list()) {
1768
1984
  addPcbHole(hole, ctx);
1769
1985
  }
1986
+ for (const cutout of db.pcb_cutout.list()) {
1987
+ addPcbCutout(cutout, ctx);
1988
+ }
1770
1989
  if (ctx.includeCopper) {
1771
1990
  for (const net of Object.keys(connMap.netMap)) {
1772
1991
  const netGeoms = ctx.netGeoms.get(net);
@@ -1787,7 +2006,7 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
1787
2006
  for (const island of union.splitToIslands()) {
1788
2007
  const { verts, prims } = polygonToShapePathData(island);
1789
2008
  project.children.push(
1790
- new ShapePath21({
2009
+ new ShapePath25({
1791
2010
  cutIndex: copperCutSetting.index,
1792
2011
  verts,
1793
2012
  prims,
@@ -0,0 +1,52 @@
1
+ import type { PcbCutoutCircle } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+ import { createCirclePath } from "../../helpers/circleShape"
5
+
6
+ /**
7
+ * Adds a circular PCB cutout to the project
8
+ * Cutouts are regions removed from the board entirely
9
+ */
10
+ export const addCirclePcbCutout = (
11
+ cutout: PcbCutoutCircle,
12
+ ctx: ConvertContext,
13
+ ): void => {
14
+ const {
15
+ project,
16
+ throughBoardCutSetting,
17
+ origin,
18
+ includeCopper,
19
+ includeSoldermask,
20
+ soldermaskMargin,
21
+ soldermaskCutSetting,
22
+ } = ctx
23
+ const centerX = cutout.center.x + origin.x
24
+ const centerY = cutout.center.y + origin.y
25
+
26
+ // Add the cutout - cut through the board
27
+ if (cutout.radius > 0 && includeCopper) {
28
+ const circlePath = createCirclePath(centerX, centerY, cutout.radius)
29
+ project.children.push(
30
+ new ShapePath({
31
+ cutIndex: throughBoardCutSetting.index,
32
+ verts: circlePath.verts,
33
+ prims: circlePath.prims,
34
+ isClosed: true,
35
+ }),
36
+ )
37
+ }
38
+
39
+ // Add soldermask opening if drawing soldermask
40
+ if (cutout.radius > 0 && includeSoldermask) {
41
+ const smRadius = cutout.radius + soldermaskMargin
42
+ const outer = createCirclePath(centerX, centerY, smRadius)
43
+ project.children.push(
44
+ new ShapePath({
45
+ cutIndex: soldermaskCutSetting.index,
46
+ verts: outer.verts,
47
+ prims: outer.prims,
48
+ isClosed: true,
49
+ }),
50
+ )
51
+ }
52
+ }
@@ -0,0 +1,73 @@
1
+ import type { PcbCutoutPath } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+
5
+ /**
6
+ * Adds a path-based PCB cutout to the project
7
+ * Path cutouts create slots along a route (e.g., for routed slots or complex cutout paths)
8
+ */
9
+ export const addPathPcbCutout = (
10
+ cutout: PcbCutoutPath,
11
+ ctx: ConvertContext,
12
+ ): void => {
13
+ const {
14
+ project,
15
+ throughBoardCutSetting,
16
+ origin,
17
+ includeCopper,
18
+ includeSoldermask,
19
+ soldermaskMargin,
20
+ soldermaskCutSetting,
21
+ } = ctx
22
+
23
+ // For path cutouts, we need to create a stroke along the route with the given width
24
+ // For simplicity, we'll convert the path to a polyline
25
+ if (cutout.route.length >= 2 && includeCopper) {
26
+ const verts: { x: number; y: number }[] = []
27
+ const prims: { type: number }[] = []
28
+
29
+ for (const point of cutout.route) {
30
+ verts.push({
31
+ x: point.x + origin.x,
32
+ y: point.y + origin.y,
33
+ })
34
+ prims.push({ type: 0 })
35
+ }
36
+
37
+ // Note: slot_width, slot_length, space_between_slots, and slot_corner_radius
38
+ // would require more complex path offsetting and aren't currently implemented
39
+ // For now, we just create a simple path along the route
40
+ project.children.push(
41
+ new ShapePath({
42
+ cutIndex: throughBoardCutSetting.index,
43
+ verts,
44
+ prims,
45
+ isClosed: false, // Paths are typically not closed
46
+ }),
47
+ )
48
+ }
49
+
50
+ // Add soldermask opening if drawing soldermask
51
+ if (cutout.route.length >= 2 && includeSoldermask) {
52
+ const verts: { x: number; y: number }[] = []
53
+ const prims: { type: number }[] = []
54
+
55
+ // Create path with soldermask margin
56
+ for (const point of cutout.route) {
57
+ verts.push({
58
+ x: point.x + origin.x,
59
+ y: point.y + origin.y,
60
+ })
61
+ prims.push({ type: 0 })
62
+ }
63
+
64
+ project.children.push(
65
+ new ShapePath({
66
+ cutIndex: soldermaskCutSetting.index,
67
+ verts,
68
+ prims,
69
+ isClosed: false, // Match the same path as the copper cutout
70
+ }),
71
+ )
72
+ }
73
+ }
@@ -0,0 +1,68 @@
1
+ import type { PcbCutoutPolygon } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+ import { createPolygonPathFromOutline } from "../../helpers/polygonShape"
5
+
6
+ /**
7
+ * Adds a polygon PCB cutout to the project
8
+ * Cutouts are regions removed from the board entirely
9
+ */
10
+ export const addPolygonPcbCutout = (
11
+ cutout: PcbCutoutPolygon,
12
+ ctx: ConvertContext,
13
+ ): void => {
14
+ const {
15
+ project,
16
+ throughBoardCutSetting,
17
+ origin,
18
+ includeCopper,
19
+ includeSoldermask,
20
+ soldermaskCutSetting,
21
+ soldermaskMargin,
22
+ } = ctx
23
+
24
+ // Add the cutout - cut through the board
25
+ if (cutout.points.length >= 3 && includeCopper) {
26
+ const polygonPath = createPolygonPathFromOutline(
27
+ cutout.points,
28
+ origin.x,
29
+ origin.y,
30
+ )
31
+ project.children.push(
32
+ new ShapePath({
33
+ cutIndex: throughBoardCutSetting.index,
34
+ verts: polygonPath.verts,
35
+ prims: polygonPath.prims,
36
+ isClosed: true,
37
+ }),
38
+ )
39
+ }
40
+
41
+ // Add soldermask opening if drawing soldermask
42
+ if (cutout.points.length >= 3 && includeSoldermask) {
43
+ // Apply soldermask margin to the points if margin is specified
44
+ const points =
45
+ soldermaskMargin && soldermaskMargin > 0
46
+ ? cutout.points.map((p) => ({
47
+ x:
48
+ (p.x ?? 0) + (p.x ?? 0) > 0
49
+ ? soldermaskMargin
50
+ : -soldermaskMargin,
51
+ y:
52
+ (p.y ?? 0) + (p.y ?? 0) > 0
53
+ ? soldermaskMargin
54
+ : -soldermaskMargin,
55
+ }))
56
+ : cutout.points
57
+
58
+ const polygonPath = createPolygonPathFromOutline(points, origin.x, origin.y)
59
+ project.children.push(
60
+ new ShapePath({
61
+ cutIndex: soldermaskCutSetting.index,
62
+ verts: polygonPath.verts,
63
+ prims: polygonPath.prims,
64
+ isClosed: true,
65
+ }),
66
+ )
67
+ }
68
+ }
@@ -0,0 +1,71 @@
1
+ import type { PcbCutoutRect } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+ import { createRoundedRectPath } from "../../helpers/roundedRectShape"
5
+
6
+ /**
7
+ * Adds a rectangular PCB cutout to the project
8
+ * Cutouts are regions removed from the board entirely
9
+ */
10
+ export const addRectPcbCutout = (
11
+ cutout: PcbCutoutRect,
12
+ ctx: ConvertContext,
13
+ ): void => {
14
+ const {
15
+ project,
16
+ throughBoardCutSetting,
17
+ origin,
18
+ includeCopper,
19
+ includeSoldermask,
20
+ soldermaskMargin,
21
+ soldermaskCutSetting,
22
+ } = ctx
23
+ const centerX = cutout.center.x + origin.x
24
+ const centerY = cutout.center.y + origin.y
25
+
26
+ // Add the cutout - cut through the board
27
+ if (cutout.width > 0 && cutout.height > 0 && includeCopper) {
28
+ const rotation = (cutout.rotation ?? 0) * (Math.PI / 180) // Convert degrees to radians
29
+ const rectPath = createRoundedRectPath(
30
+ centerX,
31
+ centerY,
32
+ cutout.width,
33
+ cutout.height,
34
+ 0, // no border radius for cutouts
35
+ 4, // segments
36
+ rotation,
37
+ )
38
+ project.children.push(
39
+ new ShapePath({
40
+ cutIndex: throughBoardCutSetting.index,
41
+ verts: rectPath.verts,
42
+ prims: rectPath.prims,
43
+ isClosed: true,
44
+ }),
45
+ )
46
+ }
47
+
48
+ // Add soldermask opening if drawing soldermask
49
+ if (cutout.width > 0 && cutout.height > 0 && includeSoldermask) {
50
+ const rotation = (cutout.rotation ?? 0) * (Math.PI / 180) // Convert degrees to radians
51
+ const smWidth = cutout.width + 2 * soldermaskMargin
52
+ const smHeight = cutout.height + 2 * soldermaskMargin
53
+ const rectPath = createRoundedRectPath(
54
+ centerX,
55
+ centerY,
56
+ smWidth,
57
+ smHeight,
58
+ 0, // no border radius for cutouts
59
+ 4, // segments
60
+ rotation,
61
+ )
62
+ project.children.push(
63
+ new ShapePath({
64
+ cutIndex: soldermaskCutSetting.index,
65
+ verts: rectPath.verts,
66
+ prims: rectPath.prims,
67
+ isClosed: true,
68
+ }),
69
+ )
70
+ }
71
+ }
@@ -0,0 +1,31 @@
1
+ import type { PcbCutout } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { addCirclePcbCutout } from "./addCirclePcbCutout"
4
+ import { addRectPcbCutout } from "./addRectPcbCutout"
5
+ import { addPolygonPcbCutout } from "./addPolygonPcbCutout"
6
+ import { addPathPcbCutout } from "./addPathPcbCutout"
7
+
8
+ /**
9
+ * Main dispatcher function that routes PCB cutouts to the appropriate handler
10
+ * based on their shape property
11
+ */
12
+ export const addPcbCutout = (cutout: PcbCutout, ctx: ConvertContext): void => {
13
+ switch (cutout.shape) {
14
+ case "circle":
15
+ return addCirclePcbCutout(cutout, ctx)
16
+
17
+ case "rect":
18
+ return addRectPcbCutout(cutout, ctx)
19
+
20
+ case "polygon":
21
+ return addPolygonPcbCutout(cutout, ctx)
22
+
23
+ case "path":
24
+ return addPathPcbCutout(cutout, ctx)
25
+
26
+ default:
27
+ // Type guard to ensure we handle all cases
28
+ const _exhaustive: never = cutout
29
+ console.warn(`Unknown cutout shape: ${(cutout as any).shape}`)
30
+ }
31
+ }
package/lib/index.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  } from "./calculateBounds"
16
16
  import { addPcbVia } from "./element-handlers/addPcbVia"
17
17
  import { addPcbHole } from "./element-handlers/addPcbHole"
18
+ import { addPcbCutout } from "./element-handlers/addPcbCutout"
18
19
  // import { writeDebugSvg } from "./writeDebugSvg"
19
20
 
20
21
  export const convertCircuitJsonToLbrn = (
@@ -114,6 +115,10 @@ export const convertCircuitJsonToLbrn = (
114
115
  addPcbHole(hole, ctx)
115
116
  }
116
117
 
118
+ for (const cutout of db.pcb_cutout.list()) {
119
+ addPcbCutout(cutout, ctx)
120
+ }
121
+
117
122
  // Draw each individual shape geometry as a ShapePath
118
123
  // FOR DEBUGGING!!!
119
124
  // for (const net of Object.keys(connMap.netMap)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "circuit-json-to-lbrn",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.17",
4
+ "version": "0.0.18",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "bun run site/index.html",
@@ -0,0 +1,8 @@
1
+ <svg width="800" height="1400" viewBox="0 0 800 1400" xmlns="http://www.w3.org/2000/svg">
2
+ <g transform="translate(0, 0)">
3
+ <style></style><rect class="boundary" x="0" y="0" fill="#000" width="800" height="600" data-type="pcb_background" data-pcb-layer="global"/><rect class="pcb-boundary" fill="none" stroke="#fff" stroke-width="0.3" x="127.27272727272725" y="27.272727272727252" width="545.4545454545455" height="545.4545454545455" data-type="pcb_boundary" data-pcb-layer="global"/><path class="pcb-board" d="M 127.27272727272725 572.7272727272727 L 672.7272727272727 572.7272727272727 L 672.7272727272727 27.272727272727252 L 127.27272727272725 27.272727272727252 Z" fill="none" stroke="rgba(255, 255, 255, 0.5)" stroke-width="2.7272727272727275" data-type="pcb_board" data-pcb-layer="board"/><circle class="pcb-cutout pcb-cutout-circle" cx="263.6363636363636" cy="163.63636363636363" r="54.54545454545455" fill="#FF26E2" data-type="pcb_cutout" data-pcb-layer="drill"/><circle class="pcb-cutout pcb-cutout-circle" cx="536.3636363636364" cy="436.3636363636364" r="81.81818181818181" fill="#FF26E2" data-type="pcb_cutout" data-pcb-layer="drill"/>
4
+ </g>
5
+ <g transform="translate(0, 600) scale(20, 20) translate(19.9, 19.9)">
6
+ <rect x="-19.9" y="-19.9" width="40" height="40" fill="white"/><g transform="matrix(1 0 0 -1 0 0.20000000000000284)"><g transform="matrix(1,0,0,1,0,0)"><path d="M -9.9 -9.9 L 10.1 -9.9 L 10.1 10.1 L -9.9 10.1 L -9.9 -9.9 L -9.9 -9.9 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M -9.9 -9.9 L 10.1 -9.9 L 10.1 10.1 L -9.9 10.1 L -9.9 -9.9 L -9.9 -9.9" fill="none" stroke="#FF0000" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M -2.9000000000000004 5.1 L -2.9096305466556065 5.2960342806591205 L -2.9384294391935395 5.4901806440322565 L -2.9861193285355827 5.680569354508925 L -3.052240934977427 5.865366864730179 L -3.1361574713032905 6.042793473651995 L -3.2370607753949097 6.211140466039204 L -3.3539790932745266 6.368786568327291 L -3.4857864376269054 6.514213562373095 L -3.6312134316727094 6.646020906725473 L -3.788859533960796 6.76293922460509 L -3.9572065263480045 6.8638425286967095 L -4.134633135269821 6.947759065022574 L -4.319430645491075 7.013880671464417 L -4.5098193559677435 7.0615705608064605 L -4.703965719340879 7.090369453344393 L -4.9 7.1 L -5.096034280659121 7.090369453344394 L -5.290180644032256 7.0615705608064605 L -5.4805693545089245 7.013880671464418 L -5.66536686473018 6.947759065022574 L -5.842793473651996 6.8638425286967095 L -6.011140466039205 6.76293922460509 L -6.168786568327291 6.646020906725473 L -6.314213562373095 6.514213562373095 L -6.446020906725474 6.368786568327291 L -6.562939224605091 6.211140466039204 L -6.66384252869671 6.0427934736519955 L -6.747759065022574 5.86536686473018 L -6.813880671464418 5.680569354508925 L -6.861570560806461 5.4901806440322565 L -6.890369453344394 5.296034280659121 L -6.9 5.1 L -6.890369453344395 4.903965719340879 L -6.861570560806461 4.709819355967743 L -6.8138806714644184 4.5194306454910755 L -6.747759065022574 4.33463313526982 L -6.66384252869671 4.157206526348005 L -6.562939224605091 3.9888595339607957 L -6.446020906725474 3.831213431672709 L -6.314213562373096 3.6857864376269047 L -6.168786568327292 3.5539790932745263 L -6.011140466039205 3.437060775394909 L -5.842793473651996 3.3361574713032898 L -5.665366864730181 3.2522409349774266 L -5.480569354508925 3.186119328535582 L -5.290180644032258 3.138429439193539 L -5.096034280659121 3.109630546655606 L -4.9 3.0999999999999996 L -4.70396571934088 3.109630546655606 L -4.5098193559677435 3.138429439193539 L -4.319430645491076 3.1861193285355816 L -4.13463313526982 3.2522409349774266 L -3.9572065263480054 3.3361574713032898 L -3.788859533960797 3.437060775394909 L -3.631213431672709 3.553979093274526 L -3.4857864376269054 3.6857864376269043 L -3.353979093274527 3.831213431672708 L -3.2370607753949097 3.9888595339607953 L -3.1361574713032905 4.157206526348004 L -3.0522409349774273 4.334633135269819 L -2.9861193285355827 4.519430645491075 L -2.9384294391935395 4.709819355967742 L -2.9096305466556065 4.903965719340879 L -2.9000000000000004 5.1 L -2.9000000000000004 5.1 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><clipPath id="clip-1764627670784-sxvpqol5n__stack1"><path d="M -2.8000000000000003 5.1 L -2.8101120739883867 5.305835994692077 L -2.8403509111532164 5.509689676233869 L -2.8904252949623617 5.709597822234371 L -2.959852981726298 5.903635207966688 L -3.0479653448684547 6.089933147334595 L -3.153913814164655 6.266697489341164 L -3.276678047938253 6.432225896743655 L -3.4150757595082504 6.584924240491749 L -3.567774103256345 6.723321952061747 L -3.7333025106588353 6.846086185835345 L -3.910066852665405 6.952034655131545 L -4.096364792033311 7.040147018273702 L -4.290402177765629 7.109574705037638 L -4.490310323766131 7.159649088846784 L -4.694164005307923 7.189887926011613 L -4.9 7.199999999999999 L -5.105835994692078 7.189887926011613 L -5.3096896762338694 7.159649088846784 L -5.509597822234371 7.109574705037638 L -5.7036352079666885 7.040147018273702 L -5.889933147334595 6.952034655131545 L -6.0666974893411645 6.846086185835345 L -6.232225896743656 6.723321952061747 L -6.38492424049175 6.58492424049175 L -6.523321952061748 6.432225896743655 L -6.646086185835346 6.266697489341164 L -6.7520346551315455 6.0899331473345955 L -6.8401470182737025 5.903635207966689 L -6.909574705037639 5.709597822234371 L -6.959649088846785 5.50968967623387 L -6.989887926011614 5.305835994692077 L -7 5.1 L -6.989887926011614 4.894164005307922 L -6.959649088846785 4.69031032376613 L -6.909574705037639 4.490402177765629 L -6.8401470182737025 4.2963647920333115 L -6.7520346551315455 4.110066852665405 L -6.646086185835346 3.9333025106588355 L -6.523321952061748 3.7677741032563445 L -6.384924240491751 3.61507575950825 L -6.232225896743657 3.4766780479382526 L -6.0666974893411645 3.3539138141646543 L -5.889933147334596 3.2479653448684545 L -5.70363520796669 3.159852981726298 L -5.5095978222343716 3.090425294962361 L -5.30968967623387 3.040350911153216 L -5.105835994692077 3.010112073988386 L -4.9 2.9999999999999996 L -4.6941640053079245 3.010112073988386 L -4.490310323766131 3.0403509111532157 L -4.29040217776563 3.090425294962361 L -4.096364792033311 3.1598529817262975 L -3.9100668526654054 3.247965344868454 L -3.7333025106588362 3.3539138141646543 L -3.567774103256345 3.476678047938252 L -3.415075759508251 3.615075759508249 L -3.2766780479382533 3.767774103256343 L -3.153913814164655 3.933302510658835 L -3.047965344868455 4.110066852665404 L -2.9598529817262986 4.29636479203331 L -2.8904252949623617 4.4904021777656284 L -2.840350911153217 4.69031032376613 L -2.8101120739883867 4.894164005307923 L -2.8000000000000003 5.1 L -2.8000000000000003 5.1 Z"/></clipPath><g clip-path="url(#clip-1764627670784-sxvpqol5n__stack1)"><line x1="-3.054344160979066" y1="2.9999999999999996" x2="-2.8000000000000003" y2="3.2543441609790653" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.308902602206223" y1="2.9999999999999996" x2="-2.8000000000000003" y2="3.508902602206222" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.5634610434333807" y1="2.9999999999999996" x2="-2.8000000000000003" y2="3.76346104343338" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.8180194846605358" y1="2.9999999999999996" x2="-2.8000000000000003" y2="4.018019484660535" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.072577925887693" y1="2.9999999999999996" x2="-2.8000000000000003" y2="4.272577925887692" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.32713636711485" y1="2.9999999999999996" x2="-2.8000000000000003" y2="4.527136367114849" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.581694808342007" y1="2.9999999999999996" x2="-2.8000000000000003" y2="4.7816948083420066" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.836253249569165" y1="2.9999999999999996" x2="-2.8000000000000003" y2="5.036253249569164" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.090811690796322" y1="2.9999999999999996" x2="-2.8000000000000003" y2="5.290811690796321" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.345370132023479" y1="2.9999999999999996" x2="-2.8000000000000003" y2="5.5453701320234785" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.5999285732506365" y1="2.9999999999999996" x2="-2.8000000000000003" y2="5.799928573250636" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.854487014477794" y1="2.9999999999999996" x2="-2.8000000000000003" y2="6.054487014477793" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.109045455704949" y1="2.9999999999999996" x2="-2.8000000000000003" y2="6.309045455704949" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.3636038969321085" y1="2.9999999999999996" x2="-2.8000000000000003" y2="6.563603896932107" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.618162338159264" y1="2.9999999999999996" x2="-2.8000000000000003" y2="6.818162338159262" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.872720779386423" y1="2.9999999999999996" x2="-2.8000000000000003" y2="7.072720779386421" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="3.127279220613578" x2="-2.9272792206135785" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="3.3818376618407364" x2="-3.181837661840738" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="3.636396103067893" x2="-3.436396103067893" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="3.890954544295052" x2="-3.690954544295052" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="4.145512985522206" x2="-3.945512985522207" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="4.4000714267493635" x2="-4.200071426749364" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="4.654629867976521" x2="-4.4546298679765215" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="4.909188309203678" x2="-4.709188309203679" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="5.163746750430835" x2="-4.963746750430836" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="5.418305191657993" x2="-5.2183051916579934" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="5.67286363288515" x2="-5.472863632885151" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="5.927422074112307" x2="-5.727422074112308" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="6.181980515339465" x2="-5.981980515339465" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="6.43653895656662" x2="-6.236538956566621" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="6.691097397793779" x2="-6.49109739779378" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-7" y1="6.945655839020935" x2="-6.745655839020936" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="6.945655839020933" x2="-3.0543441609790665" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="6.6910973977937775" x2="-3.308902602206222" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="6.4365389565666185" x2="-3.563461043433381" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="6.181980515339465" x2="-3.818019484660535" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="5.927422074112307" x2="-4.072577925887693" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="5.67286363288515" x2="-4.32713636711485" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="5.418305191657993" x2="-4.581694808342007" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="5.163746750430835" x2="-4.836253249569165" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="4.909188309203678" x2="-5.090811690796322" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="4.654629867976521" x2="-5.345370132023479" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="4.4000714267493635" x2="-5.5999285732506365" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="4.145512985522206" x2="-5.854487014477794" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="3.8909545442950506" x2="-6.109045455704948" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="3.6363961030678924" x2="-6.363603896932108" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="3.381837661840735" x2="-6.618162338159262" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.8000000000000003" y1="3.127279220613578" x2="-6.872720779386423" y2="7.199999999999999" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-2.927279220613579" y1="2.9999999999999996" x2="-7" y2="7.072720779386422" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.1818376618407362" y1="2.9999999999999996" x2="-7" y2="6.818162338159263" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.4363961030678936" y1="2.9999999999999996" x2="-7" y2="6.563603896932108" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.690954544295051" y1="2.9999999999999996" x2="-7" y2="6.309045455704949" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-3.9455129855222064" y1="2.9999999999999996" x2="-7" y2="6.054487014477793" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.200071426749364" y1="2.9999999999999996" x2="-7" y2="5.799928573250636" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.4546298679765215" y1="2.9999999999999996" x2="-7" y2="5.5453701320234785" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.709188309203679" y1="2.9999999999999996" x2="-7" y2="5.290811690796321" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-4.963746750430836" y1="2.9999999999999996" x2="-7" y2="5.036253249569164" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.2183051916579934" y1="2.9999999999999996" x2="-7" y2="4.7816948083420066" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.47286363288515" y1="2.9999999999999996" x2="-7" y2="4.527136367114849" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.727422074112307" y1="2.9999999999999996" x2="-7" y2="4.272577925887692" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-5.9819805153394645" y1="2.9999999999999996" x2="-7" y2="4.018019484660535" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.23653895656662" y1="2.9999999999999996" x2="-7" y2="3.76346104343338" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.491097397793778" y1="2.9999999999999996" x2="-7" y2="3.5089026022062213" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="-6.745655839020935" y1="2.9999999999999996" x2="-7" y2="3.254344160979065" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/></g><path d="M -2.8000000000000003 5.1 L -2.8101120739883867 5.305835994692077 L -2.8403509111532164 5.509689676233869 L -2.8904252949623617 5.709597822234371 L -2.959852981726298 5.903635207966688 L -3.0479653448684547 6.089933147334595 L -3.153913814164655 6.266697489341164 L -3.276678047938253 6.432225896743655 L -3.4150757595082504 6.584924240491749 L -3.567774103256345 6.723321952061747 L -3.7333025106588353 6.846086185835345 L -3.910066852665405 6.952034655131545 L -4.096364792033311 7.040147018273702 L -4.290402177765629 7.109574705037638 L -4.490310323766131 7.159649088846784 L -4.694164005307923 7.189887926011613 L -4.9 7.199999999999999 L -5.105835994692078 7.189887926011613 L -5.3096896762338694 7.159649088846784 L -5.509597822234371 7.109574705037638 L -5.7036352079666885 7.040147018273702 L -5.889933147334595 6.952034655131545 L -6.0666974893411645 6.846086185835345 L -6.232225896743656 6.723321952061747 L -6.38492424049175 6.58492424049175 L -6.523321952061748 6.432225896743655 L -6.646086185835346 6.266697489341164 L -6.7520346551315455 6.0899331473345955 L -6.8401470182737025 5.903635207966689 L -6.909574705037639 5.709597822234371 L -6.959649088846785 5.50968967623387 L -6.989887926011614 5.305835994692077 L -7 5.1 L -6.989887926011614 4.894164005307922 L -6.959649088846785 4.69031032376613 L -6.909574705037639 4.490402177765629 L -6.8401470182737025 4.2963647920333115 L -6.7520346551315455 4.110066852665405 L -6.646086185835346 3.9333025106588355 L -6.523321952061748 3.7677741032563445 L -6.384924240491751 3.61507575950825 L -6.232225896743657 3.4766780479382526 L -6.0666974893411645 3.3539138141646543 L -5.889933147334596 3.2479653448684545 L -5.70363520796669 3.159852981726298 L -5.5095978222343716 3.090425294962361 L -5.30968967623387 3.040350911153216 L -5.105835994692077 3.010112073988386 L -4.9 2.9999999999999996 L -4.6941640053079245 3.010112073988386 L -4.490310323766131 3.0403509111532157 L -4.29040217776563 3.090425294962361 L -4.096364792033311 3.1598529817262975 L -3.9100668526654054 3.247965344868454 L -3.7333025106588362 3.3539138141646543 L -3.567774103256345 3.476678047938252 L -3.415075759508251 3.615075759508249 L -3.2766780479382533 3.767774103256343 L -3.153913814164655 3.933302510658835 L -3.047965344868455 4.110066852665404 L -2.9598529817262986 4.29636479203331 L -2.8904252949623617 4.4904021777656284 L -2.840350911153217 4.69031032376613 L -2.8101120739883867 4.894164005307923 L -2.8000000000000003 5.1 L -2.8000000000000003 5.1 Z" fill="none" stroke="#FF0000" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M 8.1 -4.9 L 8.08555418001659 -4.605948579011319 L 8.042355841209691 -4.3147290339516156 L 7.970821007196626 -4.029145968236613 L 7.87163859753386 -3.751949702904731 L 7.7457637930450645 -3.4858097895220075 L 7.594408836907635 -3.233289300941194 L 7.41903136008821 -2.996820147509064 L 7.2213203435596425 -2.778679656440358 L 7.003179852490936 -2.5809686399117893 L 6.766710699058807 -2.4055911630923648 L 6.514190210477993 -2.2542362069549355 L 6.248050297095269 -2.1283614024661404 L 5.970854031763387 -2.0291789928033737 L 5.6852709660483844 -1.957644158790309 L 5.394051420988682 -1.9144458199834098 L 5.1 -1.9000000000000004 L 4.805948579011318 -1.9144458199834098 L 4.514729033951615 -1.957644158790309 L 4.2291459682366135 -2.0291789928033737 L 3.9519497029047304 -2.1283614024661404 L 3.6858097895220068 -2.254236206954935 L 3.433289300941194 -2.4055911630923643 L 3.1968201475090634 -2.580968639911789 L 2.9786796564403573 -2.7786796564403575 L 2.7809686399117886 -2.996820147509064 L 2.6055911630923636 -3.233289300941194 L 2.454236206954935 -3.4858097895220066 L 2.3283614024661397 -3.7519497029047306 L 2.229178992803373 -4.029145968236613 L 2.1576441587903084 -4.314729033951615 L 2.114445819983409 -4.605948579011318 L 2.0999999999999996 -4.9 L 2.114445819983409 -5.194051420988682 L 2.1576441587903084 -5.485270966048385 L 2.229178992803373 -5.7708540317633865 L 2.328361402466139 -6.048050297095269 L 2.4542362069549344 -6.314190210477993 L 2.605591163092363 -6.566710699058806 L 2.780968639911788 -6.803179852490937 L 2.978679656440357 -7.021320343559642 L 3.196820147509062 -7.21903136008821 L 3.433289300941193 -7.394408836907636 L 3.685809789522006 -7.545763793045065 L 3.9519497029047286 -7.67163859753386 L 4.229145968236613 -7.770821007196627 L 4.514729033951614 -7.842355841209692 L 4.805948579011318 -7.885554180016591 L 5.099999999999999 -7.9 L 5.39405142098868 -7.885554180016591 L 5.6852709660483844 -7.842355841209692 L 5.970854031763386 -7.770821007196627 L 6.248050297095269 -7.67163859753386 L 6.5141902104779925 -7.545763793045065 L 6.766710699058805 -7.394408836907637 L 7.003179852490936 -7.219031360088211 L 7.221320343559642 -7.021320343559643 L 7.419031360088209 -6.803179852490938 L 7.594408836907635 -6.566710699058807 L 7.7457637930450645 -6.314190210477994 L 7.87163859753386 -6.048050297095271 L 7.970821007196626 -5.770854031763388 L 8.042355841209691 -5.485270966048386 L 8.08555418001659 -5.194051420988682 L 8.1 -4.9 L 8.1 -4.9 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><clipPath id="clip-1764627670784-c401vgn6f__stack1"><path d="M 8.2 -4.9 L 8.185072652683811 -4.596146864978363 L 8.140434369250015 -4.295220001750002 L 8.066515040769847 -4.000117500511167 L 7.964026550784989 -3.713681359668222 L 7.8339559194799 -3.4386701158394075 L 7.67755579813789 -3.1777322776392336 L 7.496332405424484 -2.933380819092699 L 7.292031021678297 -2.7079689783217034 L 7.066619180907301 -2.5036675945755156 L 6.822267722360767 -2.32244420186211 L 6.5613298841605925 -2.1660440805201 L 6.286318640331778 -2.035973449215011 L 5.999882499488833 -1.933484959230153 L 5.704779998249998 -1.859565630749986 L 5.403853135021638 -1.81492734731619 L 5.1 -1.8000000000000003 L 4.796146864978361 -1.81492734731619 L 4.495220001750003 -1.859565630749986 L 4.200117500511167 -1.9334849592301526 L 3.9136813596682214 -2.035973449215011 L 3.638670115839407 -2.1660440805201 L 3.3777322776392333 -2.3224442018621096 L 3.133380819092699 -2.503667594575515 L 2.9079689783217026 -2.707968978321703 L 2.703667594575515 -2.933380819092699 L 2.522444201862109 -3.1777322776392336 L 2.366044080520099 -3.4386701158394066 L 2.2359734492150105 -3.7136813596682217 L 2.1334849592301524 -4.000117500511167 L 2.059565630749985 -4.2952200017500015 L 2.0149273473161893 -4.596146864978362 L 1.9999999999999996 -4.9 L 2.0149273473161893 -5.203853135021638 L 2.059565630749985 -5.504779998249998 L 2.133484959230152 -5.799882499488833 L 2.2359734492150105 -6.086318640331778 L 2.366044080520099 -6.361329884160593 L 2.5224442018621085 -6.622267722360767 L 2.7036675945755144 -6.866619180907301 L 2.9079689783217018 -7.092031021678297 L 3.1333808190926975 -7.296332405424485 L 3.377732277639233 -7.477555798137891 L 3.638670115839406 -7.6339559194799005 L 3.9136813596682196 -7.764026550784989 L 4.200117500511166 -7.866515040769848 L 4.495220001750001 -7.940434369250014 L 4.796146864978362 -7.985072652683811 L 5.099999999999999 -8 L 5.403853135021636 -7.985072652683811 L 5.704779998249998 -7.940434369250015 L 5.999882499488832 -7.866515040769848 L 6.286318640331778 -7.764026550784989 L 6.5613298841605925 -7.6339559194799005 L 6.822267722360765 -7.4775557981378915 L 7.066619180907301 -7.296332405424485 L 7.292031021678296 -7.092031021678299 L 7.496332405424484 -6.8666191809073025 L 7.67755579813789 -6.6222677223607676 L 7.8339559194799 -6.361329884160594 L 7.964026550784988 -6.086318640331781 L 8.066515040769847 -5.7998824994888345 L 8.140434369250013 -5.504779998249999 L 8.185072652683811 -5.203853135021638 L 8.2 -4.9 L 8.2 -4.9 Z"/></clipPath><g clip-path="url(#clip-1764627670784-c401vgn6f__stack1)"><line x1="7.982123368838192" y1="-8" x2="8.2" y2="-7.782123368838192" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.727564927611034" y1="-8" x2="8.2" y2="-7.527564927611035" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.473006486383877" y1="-8" x2="8.2" y2="-7.273006486383878" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.218448045156721" y1="-8" x2="8.2" y2="-7.018448045156721" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.963889603929562" y1="-8" x2="8.2" y2="-6.763889603929563" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.709331162702406" y1="-8" x2="8.2" y2="-6.509331162702407" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.454772721475248" y1="-8" x2="8.2" y2="-6.254772721475248" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.200214280248091" y1="-8" x2="8.2" y2="-6.000214280248092" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.945655839020935" y1="-8" x2="8.2" y2="-5.745655839020936" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.6910973977937775" y1="-8" x2="8.2" y2="-5.491097397793779" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.43653895656662" y1="-8" x2="8.2" y2="-5.236538956566621" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.181980515339465" y1="-8" x2="8.2" y2="-4.981980515339465" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.927422074112307" y1="-8" x2="8.2" y2="-4.727422074112308" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.67286363288515" y1="-8" x2="8.2" y2="-4.472863632885151" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.418305191657992" y1="-8" x2="8.2" y2="-4.2183051916579934" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.163746750430835" y1="-8" x2="8.2" y2="-3.963746750430836" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.909188309203677" y1="-8" x2="8.2" y2="-3.7091883092036797" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.654629867976521" y1="-8" x2="8.2" y2="-3.4546298679765215" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.4000714267493626" y1="-8" x2="8.2" y2="-3.200071426749365" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.145512985522206" y1="-8" x2="8.2" y2="-2.945512985522207" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.89095454429505" y1="-8" x2="8.2" y2="-2.690954544295053" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.636396103067893" y1="-8" x2="8.2" y2="-2.436396103067894" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.3818376618407355" y1="-8" x2="8.2" y2="-2.1818376618407367" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.127279220613578" y1="-8" x2="8.2" y2="-1.9272792206135794" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-7.872720779386421" x2="8.07272077938642" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-7.618162338159264" x2="7.818162338159263" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-7.363603896932107" x2="7.563603896932106" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-7.109045455704949" x2="7.309045455704949" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-6.854487014477794" x2="7.054487014477793" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-6.5999285732506365" x2="6.799928573250636" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-6.345370132023479" x2="6.5453701320234785" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-6.090811690796322" x2="6.290811690796321" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-5.836253249569165" x2="6.036253249569164" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-5.581694808342007" x2="5.781694808342007" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-5.327136367114851" x2="5.52713636711485" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-5.072577925887693" x2="5.272577925887692" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-4.818019484660535" x2="5.018019484660535" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-4.563461043433381" x2="4.76346104343338" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-4.3089026022062225" x2="4.508902602206222" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-4.054344160979066" x2="4.254344160979066" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-3.7997857197519087" x2="3.999785719751908" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-3.5452272785247514" x2="3.7452272785247507" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-3.290668837297594" x2="3.4906688372975934" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-3.0361103960704368" x2="3.236110396070436" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-2.7815519548432794" x2="2.9815519548432787" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-2.526993513616122" x2="2.7269935136161214" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-2.272435072388964" x2="2.472435072388963" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="1.9999999999999996" y1="-2.0178766311618084" x2="2.2178766311618077" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-2.0178766311618084" x2="7.982123368838192" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-2.2724350723889657" x2="7.727564927611034" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-2.526993513616123" x2="7.473006486383877" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-2.7815519548432794" x2="7.218448045156721" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-3.0361103960704376" x2="6.963889603929562" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-3.290668837297594" x2="6.709331162702406" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-3.5452272785247514" x2="6.454772721475249" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-3.7997857197519096" x2="6.20021428024809" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-4.054344160979066" x2="5.945655839020935" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-4.308902602206222" x2="5.6910973977937775" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-4.563461043433381" x2="5.43653895656662" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-4.818019484660535" x2="5.181980515339465" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-5.072577925887694" x2="4.9274220741123065" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-5.32713636711485" x2="4.67286363288515" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-5.581694808342009" x2="4.418305191657993" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-5.836253249569165" x2="4.163746750430835" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-6.090811690796324" x2="3.909188309203678" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-6.345370132023479" x2="3.654629867976521" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-6.599928573250638" x2="3.4000714267493644" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-6.854487014477794" x2="3.145512985522206" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-7.109045455704949" x2="2.8909545442950506" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-7.3636038969321085" x2="2.6363961030678924" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-7.618162338159264" x2="2.381837661840736" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.2" y1="-7.872720779386423" x2="2.1272792206135778" y2="-1.8000000000000003" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="8.07272077938642" y1="-8" x2="1.9999999999999996" y2="-1.9272792206135785" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.8181623381592615" y1="-8" x2="1.9999999999999996" y2="-2.1818376618407376" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.563603896932106" y1="-8" x2="1.9999999999999996" y2="-2.4363961030678922" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.309045455704948" y1="-8" x2="1.9999999999999996" y2="-2.690954544295052" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="7.054487014477793" y1="-8" x2="1.9999999999999996" y2="-2.945512985522207" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.799928573250636" y1="-8" x2="1.9999999999999996" y2="-3.2000714267493633" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.5453701320234785" y1="-8" x2="1.9999999999999996" y2="-3.4546298679765215" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.29081169079632" y1="-8" x2="1.9999999999999996" y2="-3.709188309203678" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="6.036253249569164" y1="-8" x2="1.9999999999999996" y2="-3.963746750430836" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.781694808342006" y1="-8" x2="1.9999999999999996" y2="-4.2183051916579934" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.527136367114849" y1="-8" x2="1.9999999999999996" y2="-4.47286363288515" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.272577925887691" y1="-8" x2="1.9999999999999996" y2="-4.727422074112307" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="5.018019484660535" y1="-8" x2="1.9999999999999996" y2="-4.981980515339465" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.76346104343338" y1="-8" x2="1.9999999999999996" y2="-5.236538956566619" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.508902602206221" y1="-8" x2="1.9999999999999996" y2="-5.491097397793778" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="4.254344160979065" y1="-8" x2="1.9999999999999996" y2="-5.745655839020934" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.999785719751908" y1="-8" x2="1.9999999999999996" y2="-6.000214280248091" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.74522727852475" y1="-8" x2="1.9999999999999996" y2="-6.254772721475249" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.4906688372975934" y1="-8" x2="1.9999999999999996" y2="-6.509331162702406" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="3.236110396070436" y1="-8" x2="1.9999999999999996" y2="-6.763889603929563" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.9815519548432787" y1="-8" x2="1.9999999999999996" y2="-7.01844804515672" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.7269935136161205" y1="-8" x2="1.9999999999999996" y2="-7.273006486383879" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.472435072388964" y1="-8" x2="1.9999999999999996" y2="-7.527564927611035" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/><line x1="2.2178766311618077" y1="-8" x2="1.9999999999999996" y2="-7.782123368838192" stroke="#FF0000" stroke-width="0.1" stroke-opacity="0.8"/></g><path d="M 8.2 -4.9 L 8.185072652683811 -4.596146864978363 L 8.140434369250015 -4.295220001750002 L 8.066515040769847 -4.000117500511167 L 7.964026550784989 -3.713681359668222 L 7.8339559194799 -3.4386701158394075 L 7.67755579813789 -3.1777322776392336 L 7.496332405424484 -2.933380819092699 L 7.292031021678297 -2.7079689783217034 L 7.066619180907301 -2.5036675945755156 L 6.822267722360767 -2.32244420186211 L 6.5613298841605925 -2.1660440805201 L 6.286318640331778 -2.035973449215011 L 5.999882499488833 -1.933484959230153 L 5.704779998249998 -1.859565630749986 L 5.403853135021638 -1.81492734731619 L 5.1 -1.8000000000000003 L 4.796146864978361 -1.81492734731619 L 4.495220001750003 -1.859565630749986 L 4.200117500511167 -1.9334849592301526 L 3.9136813596682214 -2.035973449215011 L 3.638670115839407 -2.1660440805201 L 3.3777322776392333 -2.3224442018621096 L 3.133380819092699 -2.503667594575515 L 2.9079689783217026 -2.707968978321703 L 2.703667594575515 -2.933380819092699 L 2.522444201862109 -3.1777322776392336 L 2.366044080520099 -3.4386701158394066 L 2.2359734492150105 -3.7136813596682217 L 2.1334849592301524 -4.000117500511167 L 2.059565630749985 -4.2952200017500015 L 2.0149273473161893 -4.596146864978362 L 1.9999999999999996 -4.9 L 2.0149273473161893 -5.203853135021638 L 2.059565630749985 -5.504779998249998 L 2.133484959230152 -5.799882499488833 L 2.2359734492150105 -6.086318640331778 L 2.366044080520099 -6.361329884160593 L 2.5224442018621085 -6.622267722360767 L 2.7036675945755144 -6.866619180907301 L 2.9079689783217018 -7.092031021678297 L 3.1333808190926975 -7.296332405424485 L 3.377732277639233 -7.477555798137891 L 3.638670115839406 -7.6339559194799005 L 3.9136813596682196 -7.764026550784989 L 4.200117500511166 -7.866515040769848 L 4.495220001750001 -7.940434369250014 L 4.796146864978362 -7.985072652683811 L 5.099999999999999 -8 L 5.403853135021636 -7.985072652683811 L 5.704779998249998 -7.940434369250015 L 5.999882499488832 -7.866515040769848 L 6.286318640331778 -7.764026550784989 L 6.5613298841605925 -7.6339559194799005 L 6.822267722360765 -7.4775557981378915 L 7.066619180907301 -7.296332405424485 L 7.292031021678296 -7.092031021678299 L 7.496332405424484 -6.8666191809073025 L 7.67755579813789 -6.6222677223607676 L 7.8339559194799 -6.361329884160594 L 7.964026550784988 -6.086318640331781 L 8.066515040769847 -5.7998824994888345 L 8.140434369250013 -5.504779998249999 L 8.185072652683811 -5.203853135021638 L 8.2 -4.9 L 8.2 -4.9 Z" fill="none" stroke="#FF0000" stroke-width="0.1"/></g></g>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="800" height="1400" viewBox="0 0 800 1400" xmlns="http://www.w3.org/2000/svg">
2
+ <g transform="translate(0, 0)">
3
+ <style></style><rect class="boundary" x="0" y="0" fill="#000" width="800" height="600" data-type="pcb_background" data-pcb-layer="global"/><rect class="pcb-boundary" fill="none" stroke="#fff" stroke-width="0.3" x="127.27272727272725" y="27.272727272727252" width="545.4545454545455" height="545.4545454545455" data-type="pcb_boundary" data-pcb-layer="global"/><path class="pcb-board" d="M 127.27272727272725 572.7272727272727 L 672.7272727272727 572.7272727272727 L 672.7272727272727 27.272727272727252 L 127.27272727272725 27.272727272727252 Z" fill="none" stroke="rgba(255, 255, 255, 0.5)" stroke-width="2.7272727272727275" data-type="pcb_board" data-pcb-layer="board"/>
4
+ </g>
5
+ <g transform="translate(0, 600) scale(20, 20) translate(19.9, 19.9)">
6
+ <rect x="-19.9" y="-19.9" width="40" height="40" fill="white"/><g transform="matrix(1 0 0 -1 0 0.20000000000000284)"><g transform="matrix(1,0,0,1,0,0)"><path d="M -9.9 -9.9 L 10.1 -9.9 L 10.1 10.1 L -9.9 10.1 L -9.9 -9.9 L -9.9 -9.9 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M -7.9 0.1 L -3.9 4.1 L 0.1 0.1 L -3.9 -3.9 L -7.9 0.1 L -7.9 0.1" fill="none" stroke="#0000FF" stroke-width="0.1"/></g></g>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="800" height="1400" viewBox="0 0 800 1400" xmlns="http://www.w3.org/2000/svg">
2
+ <g transform="translate(0, 0)">
3
+ <style></style><rect class="boundary" x="0" y="0" fill="#000" width="800" height="600" data-type="pcb_background" data-pcb-layer="global"/><rect class="pcb-boundary" fill="none" stroke="#fff" stroke-width="0.3" x="127.27272727272725" y="27.272727272727252" width="545.4545454545455" height="545.4545454545455" data-type="pcb_boundary" data-pcb-layer="global"/><path class="pcb-board" d="M 127.27272727272725 572.7272727272727 L 672.7272727272727 572.7272727272727 L 672.7272727272727 27.272727272727252 L 127.27272727272725 27.272727272727252 Z" fill="none" stroke="rgba(255, 255, 255, 0.5)" stroke-width="2.7272727272727275" data-type="pcb_board" data-pcb-layer="board"/><polygon class="pcb-cutout pcb-cutout-polygon" points="181.8181818181818,136.36363636363637 290.9090909090909,81.81818181818181 345.45454545454544,136.36363636363637 290.9090909090909,190.9090909090909" fill="#FF26E2" data-type="pcb_cutout" data-pcb-layer="drill"/><polygon class="pcb-cutout pcb-cutout-polygon" points="481.8181818181818,381.8181818181818 590.9090909090909,381.8181818181818 590.9090909090909,490.9090909090909 536.3636363636364,518.1818181818182 481.8181818181818,490.9090909090909" fill="#FF26E2" data-type="pcb_cutout" data-pcb-layer="drill"/>
4
+ </g>
5
+ <g transform="translate(0, 600) scale(20, 20) translate(19.9, 19.9)">
6
+ <rect x="-19.9" y="-19.9" width="40" height="40" fill="white"/><g transform="matrix(1 0 0 -1 0 0.20000000000000284)"><g transform="matrix(1,0,0,1,0,0)"><path d="M -9.9 -9.9 L 10.1 -9.9 L 10.1 10.1 L -9.9 10.1 L -9.9 -9.9 L -9.9 -9.9 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M -7.9 6.1 L -3.9 8.1 L -1.9 6.1 L -3.9 4.1 L -7.9 6.1 L -7.9 6.1 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M 3.1 -2.9 L 7.1 -2.9 L 7.1 -6.9 L 5.1 -7.9 L 3.1 -6.9 L 3.1 -2.9 L 3.1 -2.9 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g></g>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="800" height="1400" viewBox="0 0 800 1400" xmlns="http://www.w3.org/2000/svg">
2
+ <g transform="translate(0, 0)">
3
+ <style></style><rect class="boundary" x="0" y="0" fill="#000" width="800" height="600" data-type="pcb_background" data-pcb-layer="global"/><rect class="pcb-boundary" fill="none" stroke="#fff" stroke-width="0.3" x="127.27272727272725" y="27.272727272727252" width="545.4545454545455" height="545.4545454545455" data-type="pcb_boundary" data-pcb-layer="global"/><path class="pcb-board" d="M 127.27272727272725 572.7272727272727 L 672.7272727272727 572.7272727272727 L 672.7272727272727 27.272727272727252 L 127.27272727272725 27.272727272727252 Z" fill="none" stroke="rgba(255, 255, 255, 0.5)" stroke-width="2.7272727272727275" data-type="pcb_board" data-pcb-layer="board"/><rect class="pcb-cutout pcb-cutout-rect" x="-54.54545454545455" y="-40.90909090909091" width="109.0909090909091" height="81.81818181818181" fill="#FF26E2" transform="matrix(1,0,0,1,263.6363636363636,163.63636363636363)" data-type="pcb_cutout" data-pcb-layer="drill"/><rect class="pcb-cutout pcb-cutout-rect" x="-40.90909090909091" y="-54.54545454545455" width="81.81818181818181" height="109.0909090909091" fill="#FF26E2" transform="matrix(0.7071067811865476,-0.7071067811865475,0.7071067811865475,0.7071067811865476,536.3636363636364,436.3636363636364)" data-type="pcb_cutout" data-pcb-layer="drill"/>
4
+ </g>
5
+ <g transform="translate(0, 600) scale(20, 20) translate(19.9, 19.9)">
6
+ <rect x="-19.9" y="-19.9" width="40" height="40" fill="white"/><g transform="matrix(1 0 0 -1 0 0.20000000000000284)"><g transform="matrix(1,0,0,1,0,0)"><path d="M -9.9 -9.9 L 10.1 -9.9 L 10.1 10.1 L -9.9 10.1 L -9.9 -9.9 L -9.9 -9.9 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M -6.9 3.5999999999999996 L -2.9000000000000004 3.5999999999999996 L -2.9000000000000004 3.5999999999999996 L -2.9000000000000004 3.5999999999999996 L -2.9000000000000004 6.6 L -2.9000000000000004 6.6 L -2.9000000000000004 6.6 L -6.9 6.6 L -6.9 6.6 L -6.9 6.6 L -6.9 3.5999999999999996 L -6.9 3.5999999999999996 L -6.9 3.5999999999999996 L -6.9 3.5999999999999996 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g><g transform="matrix(1,0,0,1,0,0)"><path d="M 5.453553390593273 -7.374873734152917 L 7.574873734152916 -5.253553390593274 L 7.574873734152916 -5.253553390593274 L 7.574873734152916 -5.253553390593274 L 4.746446609406727 -2.425126265847084 L 4.746446609406727 -2.425126265847084 L 4.746446609406727 -2.425126265847084 L 2.6251262658470833 -4.546446609406726 L 2.6251262658470833 -4.546446609406726 L 2.6251262658470833 -4.546446609406726 L 5.453553390593273 -7.374873734152917 L 5.453553390593273 -7.374873734152917 L 5.453553390593273 -7.374873734152917 L 5.453553390593273 -7.374873734152917 Z" fill="none" stroke="#0000FF" stroke-width="0.1"/></g></g>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,49 @@
1
+ import { test, expect } from "bun:test"
2
+ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
3
+ import { generateLightBurnSvg } from "lbrnts"
4
+ import { convertCircuitJsonToLbrn } from "../../../lib"
5
+ import { stackSvgsVertically } from "stack-svgs"
6
+ import type { CircuitJson } from "circuit-json"
7
+
8
+ const circuitJson: CircuitJson = [
9
+ {
10
+ type: "pcb_board",
11
+ pcb_board_id: "board_circle_cutout",
12
+ width: 20,
13
+ height: 20,
14
+ center: { x: 0, y: 0 },
15
+ thickness: 1.6,
16
+ num_layers: 2,
17
+ material: "fr4",
18
+ },
19
+ {
20
+ type: "pcb_cutout",
21
+ pcb_cutout_id: "cutout_1",
22
+ shape: "circle",
23
+ center: { x: -5, y: 5 },
24
+ radius: 2,
25
+ },
26
+ {
27
+ type: "pcb_cutout",
28
+ pcb_cutout_id: "cutout_2",
29
+ shape: "circle",
30
+ center: { x: 5, y: -5 },
31
+ radius: 3,
32
+ },
33
+ ]
34
+
35
+ test("renders circular pcb cutouts with through-board cuts", async () => {
36
+ const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
37
+
38
+ const project = convertCircuitJsonToLbrn(circuitJson, {
39
+ includeCopper: true,
40
+ includeSoldermask: true,
41
+ soldermaskMargin: 0.1,
42
+ })
43
+
44
+ const lbrnSvg = await generateLightBurnSvg(project)
45
+
46
+ expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
47
+ import.meta.filename,
48
+ )
49
+ })
@@ -0,0 +1,44 @@
1
+ import { test, expect } from "bun:test"
2
+ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
3
+ import { generateLightBurnSvg } from "lbrnts"
4
+ import { convertCircuitJsonToLbrn } from "../../../lib"
5
+ import { stackSvgsVertically } from "stack-svgs"
6
+ import type { CircuitJson } from "circuit-json"
7
+
8
+ const circuitJson: CircuitJson = [
9
+ {
10
+ type: "pcb_board",
11
+ pcb_board_id: "board_path_cutout",
12
+ width: 20,
13
+ height: 20,
14
+ center: { x: 0, y: 0 },
15
+ thickness: 1.6,
16
+ num_layers: 2,
17
+ material: "fr4",
18
+ },
19
+ {
20
+ type: "pcb_cutout",
21
+ pcb_cutout_id: "cutout_1",
22
+ shape: "path",
23
+ route: [
24
+ { x: -8, y: 0 },
25
+ { x: -4, y: 4 },
26
+ { x: 0, y: 0 },
27
+ { x: -4, y: -4 },
28
+ { x: -8, y: 0 },
29
+ ],
30
+ slot_width: 0.5,
31
+ },
32
+ ]
33
+
34
+ test("renders path-based pcb cutouts with through-board cuts", async () => {
35
+ const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
36
+
37
+ const project = convertCircuitJsonToLbrn(circuitJson)
38
+
39
+ const lbrnSvg = await generateLightBurnSvg(project)
40
+
41
+ expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
42
+ import.meta.filename,
43
+ )
44
+ })
@@ -0,0 +1,54 @@
1
+ import { test, expect } from "bun:test"
2
+ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
3
+ import { generateLightBurnSvg } from "lbrnts"
4
+ import { convertCircuitJsonToLbrn } from "../../../lib"
5
+ import { stackSvgsVertically } from "stack-svgs"
6
+ import type { CircuitJson } from "circuit-json"
7
+
8
+ const circuitJson: CircuitJson = [
9
+ {
10
+ type: "pcb_board",
11
+ pcb_board_id: "board_polygon_cutout",
12
+ width: 20,
13
+ height: 20,
14
+ center: { x: 0, y: 0 },
15
+ thickness: 1.6,
16
+ num_layers: 2,
17
+ material: "fr4",
18
+ },
19
+ {
20
+ type: "pcb_cutout",
21
+ pcb_cutout_id: "cutout_1",
22
+ shape: "polygon",
23
+ points: [
24
+ { x: -8, y: 6 },
25
+ { x: -4, y: 8 },
26
+ { x: -2, y: 6 },
27
+ { x: -4, y: 4 },
28
+ ],
29
+ },
30
+ {
31
+ type: "pcb_cutout",
32
+ pcb_cutout_id: "cutout_2",
33
+ shape: "polygon",
34
+ points: [
35
+ { x: 3, y: -3 },
36
+ { x: 7, y: -3 },
37
+ { x: 7, y: -7 },
38
+ { x: 5, y: -8 },
39
+ { x: 3, y: -7 },
40
+ ],
41
+ },
42
+ ]
43
+
44
+ test("renders polygon pcb cutouts with through-board cuts", async () => {
45
+ const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
46
+
47
+ const project = convertCircuitJsonToLbrn(circuitJson)
48
+
49
+ const lbrnSvg = await generateLightBurnSvg(project)
50
+
51
+ expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
52
+ import.meta.filename,
53
+ )
54
+ })
@@ -0,0 +1,48 @@
1
+ import { test, expect } from "bun:test"
2
+ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
3
+ import { generateLightBurnSvg } from "lbrnts"
4
+ import { convertCircuitJsonToLbrn } from "../../../lib"
5
+ import { stackSvgsVertically } from "stack-svgs"
6
+ import type { CircuitJson } from "circuit-json"
7
+
8
+ const circuitJson: CircuitJson = [
9
+ {
10
+ type: "pcb_board",
11
+ pcb_board_id: "board_rect_cutout",
12
+ width: 20,
13
+ height: 20,
14
+ center: { x: 0, y: 0 },
15
+ thickness: 1.6,
16
+ num_layers: 2,
17
+ material: "fr4",
18
+ },
19
+ {
20
+ type: "pcb_cutout",
21
+ pcb_cutout_id: "cutout_1",
22
+ shape: "rect",
23
+ center: { x: -5, y: 5 },
24
+ width: 4,
25
+ height: 3,
26
+ },
27
+ {
28
+ type: "pcb_cutout",
29
+ pcb_cutout_id: "cutout_2",
30
+ shape: "rect",
31
+ center: { x: 5, y: -5 },
32
+ width: 3,
33
+ height: 4,
34
+ rotation: 45, // 45 degrees rotation
35
+ },
36
+ ]
37
+
38
+ test("renders rectangular pcb cutouts with through-board cuts", async () => {
39
+ const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
40
+
41
+ const project = convertCircuitJsonToLbrn(circuitJson)
42
+
43
+ const lbrnSvg = await generateLightBurnSvg(project)
44
+
45
+ expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
46
+ import.meta.filename,
47
+ )
48
+ })