circuit-to-svg 0.0.91 → 0.0.93

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
@@ -865,6 +865,345 @@ function createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY) {
865
865
  }
866
866
  var circuitJsonToPcbSvg = convertCircuitJsonToPcbSvg;
867
867
 
868
+ // lib/assembly/convert-circuit-json-to-assembly-svg.ts
869
+ import { stringify as stringify2 } from "svgson";
870
+ import { su } from "@tscircuit/soup-util";
871
+ import {
872
+ applyToPoint as applyToPoint16,
873
+ compose as compose4,
874
+ scale as scale2,
875
+ translate as translate4
876
+ } from "transformation-matrix";
877
+
878
+ // lib/assembly/svg-object-fns/create-svg-objects-from-assembly-board.ts
879
+ import { applyToPoint as applyToPoint13 } from "transformation-matrix";
880
+ var DEFAULT_BOARD_STYLE = {
881
+ fill: "none",
882
+ stroke: "rgb(0,0,0)",
883
+ strokeOpacity: "0.8",
884
+ strokeWidthFactor: 0.2
885
+ };
886
+ function createSvgObjectsFromAssemblyBoard(pcbBoard, transform, style = {}) {
887
+ const { width, height, center, outline } = pcbBoard;
888
+ let path;
889
+ if (outline && Array.isArray(outline) && outline.length >= 3) {
890
+ path = outline.map((point, index) => {
891
+ const [x, y] = applyToPoint13(transform, [point.x, point.y]);
892
+ return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
893
+ }).join(" ");
894
+ } else {
895
+ const halfWidth = width / 2;
896
+ const halfHeight = height / 2;
897
+ const topLeft = applyToPoint13(transform, [
898
+ center.x - halfWidth,
899
+ center.y - halfHeight
900
+ ]);
901
+ const topRight = applyToPoint13(transform, [
902
+ center.x + halfWidth,
903
+ center.y - halfHeight
904
+ ]);
905
+ const bottomRight = applyToPoint13(transform, [
906
+ center.x + halfWidth,
907
+ center.y + halfHeight
908
+ ]);
909
+ const bottomLeft = applyToPoint13(transform, [
910
+ center.x - halfWidth,
911
+ center.y + halfHeight
912
+ ]);
913
+ path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`;
914
+ }
915
+ path += " Z";
916
+ return [
917
+ {
918
+ name: "path",
919
+ type: "element",
920
+ value: "",
921
+ children: [],
922
+ attributes: {
923
+ class: "pcb-board",
924
+ d: path,
925
+ fill: style.fill ?? DEFAULT_BOARD_STYLE.fill,
926
+ stroke: style.stroke ?? DEFAULT_BOARD_STYLE.stroke,
927
+ "stroke-opacity": style.strokeOpacity ?? DEFAULT_BOARD_STYLE.strokeOpacity,
928
+ "stroke-width": ((style.strokeWidthFactor ?? DEFAULT_BOARD_STYLE.strokeWidthFactor) * Math.abs(transform.a)).toString()
929
+ }
930
+ }
931
+ ];
932
+ }
933
+
934
+ // lib/assembly/svg-object-fns/create-svg-objects-from-assembly-component.ts
935
+ import { applyToPoint as applyToPoint15 } from "transformation-matrix";
936
+
937
+ // lib/utils/get-sch-font-size.ts
938
+ import "transformation-matrix";
939
+ var getSchMmFontSize = (textType) => {
940
+ return textType === "error" ? 0.05 : textType === "pin_number" ? 0.15 : 0.18;
941
+ };
942
+ var getSchScreenFontSize = (transform, textType) => {
943
+ return Math.abs(transform.a) * getSchMmFontSize(textType);
944
+ };
945
+
946
+ // lib/assembly/svg-object-fns/create-svg-objects-from-assembly-component.ts
947
+ function createSvgObjectsFromAssemblyComponent(component, transform, firstPin, name) {
948
+ const { center, width, height, rotation = 0 } = component;
949
+ const [x, y] = applyToPoint15(transform, [center.x, center.y]);
950
+ const [pinX, pinY] = applyToPoint15(transform, [firstPin.x, firstPin.y]);
951
+ const scaledWidth = width * Math.abs(transform.a);
952
+ const scaledHeight = height * Math.abs(transform.d);
953
+ return {
954
+ name: "g",
955
+ type: "element",
956
+ value: "",
957
+ attributes: {
958
+ transform: `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`
959
+ },
960
+ children: [
961
+ createComponentPath(
962
+ scaledWidth,
963
+ scaledHeight,
964
+ x,
965
+ y,
966
+ pinX,
967
+ pinY,
968
+ rotation
969
+ ),
970
+ createComponentLabel(scaledWidth, scaledHeight, name ?? "", transform)
971
+ ]
972
+ };
973
+ }
974
+ function createComponentPath(scaledWidth, scaledHeight, centerX, centerY, pinX, pinY, rotation) {
975
+ const w = scaledWidth / 2;
976
+ const h = scaledHeight / 2;
977
+ const cornerSize = Math.min(w, h) * 0.3;
978
+ const isTop = pinY > centerY;
979
+ const isLeft = pinX < centerX;
980
+ const path = getComponentPathData(w, h, cornerSize, isTop, isLeft, rotation);
981
+ return {
982
+ name: "path",
983
+ type: "element",
984
+ attributes: {
985
+ class: "assembly-component",
986
+ d: path
987
+ },
988
+ value: "",
989
+ children: []
990
+ };
991
+ }
992
+ function createComponentLabel(scaledWidth, scaledHeight, name, transform) {
993
+ const scale7 = Math.min(scaledWidth, scaledHeight) * 0.4;
994
+ const fontSize = getSchScreenFontSize(transform, "net_label") * (scale7 / 2.5);
995
+ const scaledFontSize = scale7 < 25 ? fontSize : fontSize * 0.6;
996
+ return {
997
+ name: "text",
998
+ type: "element",
999
+ attributes: {
1000
+ x: "0",
1001
+ y: `${0 + scaledFontSize / 8}`,
1002
+ class: "assembly-component-label",
1003
+ "text-anchor": "middle",
1004
+ "dominant-baseline": "middle",
1005
+ "font-size": `${scaledFontSize}px`,
1006
+ transform: "scale(1, -1)"
1007
+ },
1008
+ children: [
1009
+ {
1010
+ type: "text",
1011
+ value: name || "",
1012
+ name: "",
1013
+ attributes: {},
1014
+ children: []
1015
+ }
1016
+ ],
1017
+ value: ""
1018
+ };
1019
+ }
1020
+ function getComponentPathData(w, h, cornerSize, isTop, isLeft, rotation) {
1021
+ const rotatePoint = (x, y, angle) => {
1022
+ const rad = Math.PI / 180 * angle;
1023
+ const cos = Math.cos(rad);
1024
+ const sin = Math.sin(rad);
1025
+ return [x * cos - y * sin, x * sin + y * cos];
1026
+ };
1027
+ let corners;
1028
+ if (isTop && isLeft) {
1029
+ corners = [
1030
+ [-w, -h + cornerSize],
1031
+ [-w + cornerSize, -h],
1032
+ [w, -h],
1033
+ [w, h],
1034
+ [-w, h]
1035
+ ];
1036
+ } else if (isTop && !isLeft) {
1037
+ corners = [
1038
+ [-w, -h],
1039
+ [w - cornerSize, -h],
1040
+ [w, -h + cornerSize],
1041
+ [w, h],
1042
+ [-w, h]
1043
+ ];
1044
+ } else if (!isTop && isLeft) {
1045
+ corners = [
1046
+ [-w, -h],
1047
+ [w, -h],
1048
+ [w, h],
1049
+ [-w + cornerSize, h],
1050
+ [-w, h - cornerSize]
1051
+ ];
1052
+ } else {
1053
+ corners = [
1054
+ [-w, -h],
1055
+ [w, -h],
1056
+ [w, h - cornerSize],
1057
+ [w - cornerSize, h],
1058
+ [-w, h]
1059
+ ];
1060
+ }
1061
+ const rotatedCorners = corners.map(([x, y]) => rotatePoint(x, y, rotation));
1062
+ const path = rotatedCorners.map(([x, y], index) => index === 0 ? `M${x},${y}` : `L${x},${y}`).join(" ");
1063
+ return `${path} Z`;
1064
+ }
1065
+
1066
+ // lib/assembly/convert-circuit-json-to-assembly-svg.ts
1067
+ var OBJECT_ORDER2 = ["pcb_board", "pcb_component"];
1068
+ function convertCircuitJsonToAssemblySvg(soup, options) {
1069
+ let minX = Number.POSITIVE_INFINITY;
1070
+ let minY = Number.POSITIVE_INFINITY;
1071
+ let maxX = Number.NEGATIVE_INFINITY;
1072
+ let maxY = Number.NEGATIVE_INFINITY;
1073
+ for (const item of soup) {
1074
+ if (item.type === "pcb_board") {
1075
+ const center = item.center;
1076
+ const width = item.width || 0;
1077
+ const height = item.height || 0;
1078
+ minX = Math.min(minX, center.x - width / 2);
1079
+ minY = Math.min(minY, center.y - height / 2);
1080
+ maxX = Math.max(maxX, center.x + width / 2);
1081
+ maxY = Math.max(maxY, center.y + height / 2);
1082
+ }
1083
+ }
1084
+ const padding = 1;
1085
+ const circuitWidth = maxX - minX + 2 * padding;
1086
+ const circuitHeight = maxY - minY + 2 * padding;
1087
+ const svgWidth = options?.width ?? 800;
1088
+ const svgHeight = options?.height ?? 600;
1089
+ const scaleX = svgWidth / circuitWidth;
1090
+ const scaleY = svgHeight / circuitHeight;
1091
+ const scaleFactor = Math.min(scaleX, scaleY);
1092
+ const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
1093
+ const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
1094
+ const transform = compose4(
1095
+ translate4(
1096
+ offsetX - minX * scaleFactor + padding * scaleFactor,
1097
+ svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
1098
+ ),
1099
+ scale2(scaleFactor, -scaleFactor)
1100
+ // Flip in y-direction
1101
+ );
1102
+ const svgObjects = soup.sort(
1103
+ (a, b) => (OBJECT_ORDER2.indexOf(b.type) ?? 9999) - (OBJECT_ORDER2.indexOf(a.type) ?? 9999)
1104
+ ).flatMap((item) => createSvgObjects2(item, transform, soup));
1105
+ const svgObject = {
1106
+ name: "svg",
1107
+ type: "element",
1108
+ attributes: {
1109
+ xmlns: "http://www.w3.org/2000/svg",
1110
+ width: svgWidth.toString(),
1111
+ height: svgHeight.toString()
1112
+ },
1113
+ value: "",
1114
+ children: [
1115
+ {
1116
+ name: "style",
1117
+ type: "element",
1118
+ children: [
1119
+ {
1120
+ type: "text",
1121
+ value: `
1122
+ .assembly-component { fill: #fff; stroke: #000; stroke-width: 3; }
1123
+ .assembly-board { fill: #f2f2f2; stroke: rgb(0,0,0); stroke-opacity: 0.8; }
1124
+ .assembly-component-label {
1125
+ fill: #000;
1126
+ font-family: Arial, serif;
1127
+ font-weight: bold;
1128
+ }
1129
+ .assembly-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }
1130
+ `,
1131
+ name: "",
1132
+ attributes: {},
1133
+ children: []
1134
+ }
1135
+ ],
1136
+ value: "",
1137
+ attributes: {}
1138
+ },
1139
+ {
1140
+ name: "rect",
1141
+ type: "element",
1142
+ attributes: {
1143
+ fill: "#fff",
1144
+ x: "0",
1145
+ y: "0",
1146
+ width: svgWidth.toString(),
1147
+ height: svgHeight.toString()
1148
+ },
1149
+ value: "",
1150
+ children: []
1151
+ },
1152
+ createSvgObjectFromAssemblyBoundary(transform, minX, minY, maxX, maxY),
1153
+ ...svgObjects
1154
+ ].filter((child) => child !== null)
1155
+ };
1156
+ return stringify2(svgObject);
1157
+ }
1158
+ function createSvgObjects2(elm, transform, soup) {
1159
+ const sourceComponents = su(soup).source_component.list();
1160
+ switch (elm.type) {
1161
+ case "pcb_board":
1162
+ return createSvgObjectsFromAssemblyBoard(elm, transform);
1163
+ case "pcb_component": {
1164
+ const sourceComponent = sourceComponents.find(
1165
+ (item) => item.source_component_id === elm.source_component_id
1166
+ );
1167
+ const ports = su(soup).pcb_port.list().filter((port) => port.pcb_component_id === elm.pcb_component_id);
1168
+ const firstPort = ports[0];
1169
+ if (sourceComponent && firstPort) {
1170
+ return [
1171
+ createSvgObjectsFromAssemblyComponent(
1172
+ elm,
1173
+ transform,
1174
+ { x: firstPort.x, y: firstPort.y },
1175
+ sourceComponent.name
1176
+ )
1177
+ ].filter(Boolean);
1178
+ }
1179
+ return [];
1180
+ }
1181
+ default:
1182
+ return [];
1183
+ }
1184
+ }
1185
+ function createSvgObjectFromAssemblyBoundary(transform, minX, minY, maxX, maxY) {
1186
+ const [x1, y1] = applyToPoint16(transform, [minX, minY]);
1187
+ const [x2, y2] = applyToPoint16(transform, [maxX, maxY]);
1188
+ const width = Math.abs(x2 - x1);
1189
+ const height = Math.abs(y2 - y1);
1190
+ const x = Math.min(x1, x2);
1191
+ const y = Math.min(y1, y2);
1192
+ return {
1193
+ name: "rect",
1194
+ type: "element",
1195
+ value: "",
1196
+ children: [],
1197
+ attributes: {
1198
+ class: "assembly-boundary",
1199
+ x: x.toString(),
1200
+ y: y.toString(),
1201
+ width: width.toString(),
1202
+ height: height.toString()
1203
+ }
1204
+ };
1205
+ }
1206
+
868
1207
  // lib/utils/colors.ts
869
1208
  var colorMap = {
870
1209
  "3d_viewer": {
@@ -1103,20 +1442,20 @@ var colorMap = {
1103
1442
  };
1104
1443
 
1105
1444
  // lib/sch/convert-circuit-json-to-schematic-svg.ts
1106
- import { stringify as stringify2 } from "svgson";
1445
+ import { stringify as stringify3 } from "svgson";
1107
1446
  import {
1108
1447
  fromTriangles
1109
1448
  } from "transformation-matrix";
1110
1449
 
1111
1450
  // lib/sch/draw-schematic-grid.ts
1112
- import { applyToPoint as applyToPoint13 } from "transformation-matrix";
1451
+ import { applyToPoint as applyToPoint17 } from "transformation-matrix";
1113
1452
  function drawSchematicGrid(params) {
1114
1453
  const { minX, minY, maxX, maxY } = params.bounds;
1115
1454
  const cellSize = params.cellSize ?? 1;
1116
1455
  const labelCells = params.labelCells ?? false;
1117
1456
  const gridLines = [];
1118
1457
  const transformPoint = (x, y) => {
1119
- const [transformedX, transformedY] = applyToPoint13(params.transform, [x, y]);
1458
+ const [transformedX, transformedY] = applyToPoint17(params.transform, [x, y]);
1120
1459
  return { x: transformedX, y: transformedY };
1121
1460
  };
1122
1461
  for (let x = Math.floor(minX); x <= Math.ceil(maxX); x += cellSize) {
@@ -1197,15 +1536,15 @@ function drawSchematicGrid(params) {
1197
1536
  }
1198
1537
 
1199
1538
  // lib/sch/draw-schematic-labeled-points.ts
1200
- import { applyToPoint as applyToPoint14 } from "transformation-matrix";
1539
+ import { applyToPoint as applyToPoint18 } from "transformation-matrix";
1201
1540
  function drawSchematicLabeledPoints(params) {
1202
1541
  const { points, transform } = params;
1203
1542
  const labeledPointsGroup = [];
1204
1543
  for (const point of points) {
1205
- const [x1, y1] = applyToPoint14(transform, [point.x - 0.1, point.y - 0.1]);
1206
- const [x2, y2] = applyToPoint14(transform, [point.x + 0.1, point.y + 0.1]);
1207
- const [x3, y3] = applyToPoint14(transform, [point.x - 0.1, point.y + 0.1]);
1208
- const [x4, y4] = applyToPoint14(transform, [point.x + 0.1, point.y - 0.1]);
1544
+ const [x1, y1] = applyToPoint18(transform, [point.x - 0.1, point.y - 0.1]);
1545
+ const [x2, y2] = applyToPoint18(transform, [point.x + 0.1, point.y + 0.1]);
1546
+ const [x3, y3] = applyToPoint18(transform, [point.x - 0.1, point.y + 0.1]);
1547
+ const [x4, y4] = applyToPoint18(transform, [point.x + 0.1, point.y - 0.1]);
1209
1548
  labeledPointsGroup.push({
1210
1549
  name: "path",
1211
1550
  type: "element",
@@ -1216,7 +1555,7 @@ function drawSchematicLabeledPoints(params) {
1216
1555
  "stroke-opacity": "0.7"
1217
1556
  }
1218
1557
  });
1219
- const [labelX, labelY] = applyToPoint14(transform, [
1558
+ const [labelX, labelY] = applyToPoint18(transform, [
1220
1559
  point.x + 0.15,
1221
1560
  point.y - 0.15
1222
1561
  ]);
@@ -1309,12 +1648,12 @@ function getSchematicBoundsFromCircuitJson(soup, padding = 0.5) {
1309
1648
  }
1310
1649
 
1311
1650
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-symbol.ts
1312
- import { su } from "@tscircuit/soup-util";
1651
+ import { su as su2 } from "@tscircuit/soup-util";
1313
1652
  import { symbols } from "schematic-symbols";
1314
1653
  import "svgson";
1315
1654
  import {
1316
- applyToPoint as applyToPoint17,
1317
- compose as compose5
1655
+ applyToPoint as applyToPoint20,
1656
+ compose as compose6
1318
1657
  } from "transformation-matrix";
1319
1658
 
1320
1659
  // lib/utils/get-sch-stroke-size.ts
@@ -1384,35 +1723,26 @@ var matchSchPortsToSymbolPorts = ({
1384
1723
  };
1385
1724
 
1386
1725
  // lib/utils/point-pairs-to-matrix.ts
1387
- import { compose as compose4, scale as scale2, translate as translate4 } from "transformation-matrix";
1726
+ import { compose as compose5, scale as scale3, translate as translate5 } from "transformation-matrix";
1388
1727
  function pointPairsToMatrix(a1, a2, b1, b2) {
1389
1728
  const tx = a2.x - a1.x;
1390
1729
  const ty = a2.y - a1.y;
1391
1730
  const originalDistance = Math.sqrt((b1.x - a1.x) ** 2 + (b1.y - a1.y) ** 2);
1392
1731
  const transformedDistance = Math.sqrt((b2.x - a2.x) ** 2 + (b2.y - a2.y) ** 2);
1393
1732
  const a = transformedDistance / originalDistance;
1394
- const translateMatrix = translate4(tx, ty);
1395
- const scaleMatrix = scale2(a, a);
1396
- return compose4(translateMatrix, scaleMatrix);
1733
+ const translateMatrix = translate5(tx, ty);
1734
+ const scaleMatrix = scale3(a, a);
1735
+ return compose5(translateMatrix, scaleMatrix);
1397
1736
  }
1398
1737
 
1399
- // lib/utils/get-sch-font-size.ts
1400
- import "transformation-matrix";
1401
- var getSchMmFontSize = (textType) => {
1402
- return textType === "error" ? 0.05 : textType === "pin_number" ? 0.15 : 0.18;
1403
- };
1404
- var getSchScreenFontSize = (transform, textType) => {
1405
- return Math.abs(transform.a) * getSchMmFontSize(textType);
1406
- };
1407
-
1408
1738
  // lib/sch/svg-object-fns/create-svg-error-text.ts
1409
- import { applyToPoint as applyToPoint16 } from "transformation-matrix";
1739
+ import { applyToPoint as applyToPoint19 } from "transformation-matrix";
1410
1740
  var createSvgSchErrorText = ({
1411
1741
  text,
1412
1742
  realCenter,
1413
1743
  realToScreenTransform
1414
1744
  }) => {
1415
- const screenCenter = applyToPoint16(realToScreenTransform, realCenter);
1745
+ const screenCenter = applyToPoint19(realToScreenTransform, realCenter);
1416
1746
  return {
1417
1747
  type: "element",
1418
1748
  name: "text",
@@ -1477,10 +1807,10 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1477
1807
  })
1478
1808
  ];
1479
1809
  }
1480
- const schPorts = su(circuitJson).schematic_port.list({
1810
+ const schPorts = su2(circuitJson).schematic_port.list({
1481
1811
  schematic_component_id: schComponent.schematic_component_id
1482
1812
  });
1483
- const srcComponent = su(circuitJson).source_component.get(
1813
+ const srcComponent = su2(circuitJson).source_component.get(
1484
1814
  schComponent.source_component_id
1485
1815
  );
1486
1816
  const schPortsWithSymbolPorts = matchSchPortsToSymbolPorts({
@@ -1513,12 +1843,12 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1513
1843
  minY: Math.min(...paths.flatMap((p) => p.points.map((pt) => pt.y))),
1514
1844
  maxY: Math.max(...paths.flatMap((p) => p.points.map((pt) => pt.y)))
1515
1845
  };
1516
- const [screenMinX, screenMinY] = applyToPoint17(
1517
- compose5(realToScreenTransform, transformFromSymbolToReal),
1846
+ const [screenMinX, screenMinY] = applyToPoint20(
1847
+ compose6(realToScreenTransform, transformFromSymbolToReal),
1518
1848
  [bounds.minX, bounds.minY]
1519
1849
  );
1520
- const [screenMaxX, screenMaxY] = applyToPoint17(
1521
- compose5(realToScreenTransform, transformFromSymbolToReal),
1850
+ const [screenMaxX, screenMaxY] = applyToPoint20(
1851
+ compose6(realToScreenTransform, transformFromSymbolToReal),
1522
1852
  [bounds.maxX, bounds.maxY]
1523
1853
  );
1524
1854
  const rectHeight = Math.abs(screenMaxY - screenMinY);
@@ -1546,8 +1876,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1546
1876
  name: "path",
1547
1877
  attributes: {
1548
1878
  d: points.map((p, i) => {
1549
- const [x, y] = applyToPoint17(
1550
- compose5(realToScreenTransform, transformFromSymbolToReal),
1879
+ const [x, y] = applyToPoint20(
1880
+ compose6(realToScreenTransform, transformFromSymbolToReal),
1551
1881
  [p.x, p.y]
1552
1882
  );
1553
1883
  return `${i === 0 ? "M" : "L"} ${x} ${y}`;
@@ -1561,8 +1891,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1561
1891
  });
1562
1892
  }
1563
1893
  for (const text of texts) {
1564
- const screenTextPos = applyToPoint17(
1565
- compose5(realToScreenTransform, transformFromSymbolToReal),
1894
+ const screenTextPos = applyToPoint20(
1895
+ compose6(realToScreenTransform, transformFromSymbolToReal),
1566
1896
  text
1567
1897
  );
1568
1898
  let textValue = "";
@@ -1595,11 +1925,11 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1595
1925
  });
1596
1926
  }
1597
1927
  for (const box of boxes) {
1598
- const screenBoxPos = applyToPoint17(
1599
- compose5(realToScreenTransform, transformFromSymbolToReal),
1928
+ const screenBoxPos = applyToPoint20(
1929
+ compose6(realToScreenTransform, transformFromSymbolToReal),
1600
1930
  box
1601
1931
  );
1602
- const symbolToScreenScale = compose5(
1932
+ const symbolToScreenScale = compose6(
1603
1933
  realToScreenTransform,
1604
1934
  transformFromSymbolToReal
1605
1935
  ).a;
@@ -1618,8 +1948,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1618
1948
  });
1619
1949
  }
1620
1950
  for (const port of symbol.ports) {
1621
- const screenPortPos = applyToPoint17(
1622
- compose5(realToScreenTransform, transformFromSymbolToReal),
1951
+ const screenPortPos = applyToPoint20(
1952
+ compose6(realToScreenTransform, transformFromSymbolToReal),
1623
1953
  port
1624
1954
  );
1625
1955
  svgObjects.push({
@@ -1641,18 +1971,18 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1641
1971
  };
1642
1972
 
1643
1973
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-box.ts
1644
- import { su as su4 } from "@tscircuit/soup-util";
1974
+ import { su as su5 } from "@tscircuit/soup-util";
1645
1975
  import "schematic-symbols";
1646
1976
  import "svgson";
1647
- import { applyToPoint as applyToPoint22 } from "transformation-matrix";
1977
+ import { applyToPoint as applyToPoint25 } from "transformation-matrix";
1648
1978
 
1649
1979
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-port-on-box.ts
1650
1980
  import "transformation-matrix";
1651
1981
  import "@tscircuit/soup-util";
1652
1982
 
1653
1983
  // lib/sch/svg-object-fns/create-svg-objects-for-sch-port-box-line.ts
1654
- import { applyToPoint as applyToPoint18 } from "transformation-matrix";
1655
- import { su as su2 } from "@tscircuit/soup-util";
1984
+ import { applyToPoint as applyToPoint21 } from "transformation-matrix";
1985
+ import { su as su3 } from "@tscircuit/soup-util";
1656
1986
  var PIN_CIRCLE_RADIUS_MM = 0.02;
1657
1987
  var createSvgObjectsForSchPortBoxLine = ({
1658
1988
  schPort,
@@ -1661,7 +1991,7 @@ var createSvgObjectsForSchPortBoxLine = ({
1661
1991
  circuitJson
1662
1992
  }) => {
1663
1993
  const svgObjects = [];
1664
- const srcPort = su2(circuitJson).source_port.get(schPort.source_port_id);
1994
+ const srcPort = su3(circuitJson).source_port.get(schPort.source_port_id);
1665
1995
  const realEdgePos = {
1666
1996
  x: schPort.center.x,
1667
1997
  y: schPort.center.y
@@ -1681,8 +2011,8 @@ var createSvgObjectsForSchPortBoxLine = ({
1681
2011
  realEdgePos.y += realPinLineLength;
1682
2012
  break;
1683
2013
  }
1684
- const screenSchPortPos = applyToPoint18(transform, schPort.center);
1685
- const screenRealEdgePos = applyToPoint18(transform, realEdgePos);
2014
+ const screenSchPortPos = applyToPoint21(transform, schPort.center);
2015
+ const screenRealEdgePos = applyToPoint21(transform, realEdgePos);
1686
2016
  const realLineEnd = { ...schPort.center };
1687
2017
  switch (schPort.side_of_component) {
1688
2018
  case "left":
@@ -1698,7 +2028,7 @@ var createSvgObjectsForSchPortBoxLine = ({
1698
2028
  realLineEnd.y += PIN_CIRCLE_RADIUS_MM;
1699
2029
  break;
1700
2030
  }
1701
- const screenLineEnd = applyToPoint18(transform, realLineEnd);
2031
+ const screenLineEnd = applyToPoint21(transform, realLineEnd);
1702
2032
  svgObjects.push({
1703
2033
  name: "line",
1704
2034
  type: "element",
@@ -1745,7 +2075,7 @@ var getUnitVectorFromOutsideToEdge = (side) => {
1745
2075
  };
1746
2076
 
1747
2077
  // lib/sch/svg-object-fns/create-svg-objects-for-sch-port-pin-number-text.ts
1748
- import { applyToPoint as applyToPoint19 } from "transformation-matrix";
2078
+ import { applyToPoint as applyToPoint22 } from "transformation-matrix";
1749
2079
  var createSvgObjectsForSchPortPinNumberText = (params) => {
1750
2080
  const svgObjects = [];
1751
2081
  const { schPort, schComponent, transform, circuitJson } = params;
@@ -1763,7 +2093,7 @@ var createSvgObjectsForSchPortPinNumberText = (params) => {
1763
2093
  } else {
1764
2094
  realPinNumberPos.y += 0.02;
1765
2095
  }
1766
- const screenPinNumberTextPos = applyToPoint19(transform, realPinNumberPos);
2096
+ const screenPinNumberTextPos = applyToPoint22(transform, realPinNumberPos);
1767
2097
  svgObjects.push({
1768
2098
  name: "text",
1769
2099
  type: "element",
@@ -1793,7 +2123,7 @@ var createSvgObjectsForSchPortPinNumberText = (params) => {
1793
2123
  };
1794
2124
 
1795
2125
  // lib/sch/svg-object-fns/create-svg-objects-for-sch-port-pin-label.ts
1796
- import { applyToPoint as applyToPoint20 } from "transformation-matrix";
2126
+ import { applyToPoint as applyToPoint23 } from "transformation-matrix";
1797
2127
  var LABEL_DIST_FROM_EDGE_MM = 0.1;
1798
2128
  var createSvgObjectsForSchPortPinLabel = (params) => {
1799
2129
  const svgObjects = [];
@@ -1807,7 +2137,7 @@ var createSvgObjectsForSchPortPinLabel = (params) => {
1807
2137
  const realPinEdgeDistance = schPort.distance_from_component_edge ?? 0.4;
1808
2138
  realPinNumberPos.x += vecToEdge.x * (realPinEdgeDistance + LABEL_DIST_FROM_EDGE_MM);
1809
2139
  realPinNumberPos.y += vecToEdge.y * (realPinEdgeDistance + LABEL_DIST_FROM_EDGE_MM);
1810
- const screenPinNumberTextPos = applyToPoint20(transform, realPinNumberPos);
2140
+ const screenPinNumberTextPos = applyToPoint23(transform, realPinNumberPos);
1811
2141
  const label = schPort.display_pin_label ?? schComponent.port_labels?.[`${schPort.pin_number}`];
1812
2142
  if (!label) return [];
1813
2143
  svgObjects.push({
@@ -1855,11 +2185,11 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
1855
2185
  circuitJson
1856
2186
  }) => {
1857
2187
  const svgObjects = [];
1858
- const componentScreenTopLeft = applyToPoint22(transform, {
2188
+ const componentScreenTopLeft = applyToPoint25(transform, {
1859
2189
  x: schComponent.center.x - schComponent.size.width / 2,
1860
2190
  y: schComponent.center.y + schComponent.size.height / 2
1861
2191
  });
1862
- const componentScreenBottomRight = applyToPoint22(transform, {
2192
+ const componentScreenBottomRight = applyToPoint25(transform, {
1863
2193
  x: schComponent.center.x + schComponent.size.width / 2,
1864
2194
  y: schComponent.center.y - schComponent.size.height / 2
1865
2195
  });
@@ -1895,7 +2225,7 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
1895
2225
  },
1896
2226
  children: []
1897
2227
  });
1898
- const schematicPorts = su4(circuitJson).schematic_port.list({
2228
+ const schematicPorts = su5(circuitJson).schematic_port.list({
1899
2229
  schematic_component_id: schComponent.schematic_component_id
1900
2230
  });
1901
2231
  for (const schPort of schematicPorts) {
@@ -1930,9 +2260,9 @@ function createSvgObjectsFromSchematicComponent(params) {
1930
2260
  }
1931
2261
 
1932
2262
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-voltage-probe.ts
1933
- import { applyToPoint as applyToPoint23 } from "transformation-matrix";
2263
+ import { applyToPoint as applyToPoint26 } from "transformation-matrix";
1934
2264
  function createSvgObjectsFromSchVoltageProbe(probe, transform) {
1935
- const [screenX, screenY] = applyToPoint23(transform, [
2265
+ const [screenX, screenY] = applyToPoint26(transform, [
1936
2266
  probe.position.x,
1937
2267
  probe.position.y
1938
2268
  ]);
@@ -1992,14 +2322,14 @@ function createSvgObjectsFromSchVoltageProbe(probe, transform) {
1992
2322
  }
1993
2323
 
1994
2324
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-debug-object.ts
1995
- import { applyToPoint as applyToPoint24 } from "transformation-matrix";
2325
+ import { applyToPoint as applyToPoint27 } from "transformation-matrix";
1996
2326
  function createSvgObjectsFromSchDebugObject(debugObject, transform) {
1997
2327
  if (debugObject.shape === "rect") {
1998
- let [screenLeft, screenTop] = applyToPoint24(transform, [
2328
+ let [screenLeft, screenTop] = applyToPoint27(transform, [
1999
2329
  debugObject.center.x - debugObject.size.width / 2,
2000
2330
  debugObject.center.y - debugObject.size.height / 2
2001
2331
  ]);
2002
- let [screenRight, screenBottom] = applyToPoint24(transform, [
2332
+ let [screenRight, screenBottom] = applyToPoint27(transform, [
2003
2333
  debugObject.center.x + debugObject.size.width / 2,
2004
2334
  debugObject.center.y + debugObject.size.height / 2
2005
2335
  ]);
@@ -2009,7 +2339,7 @@ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
2009
2339
  ];
2010
2340
  const width = Math.abs(screenRight - screenLeft);
2011
2341
  const height = Math.abs(screenBottom - screenTop);
2012
- const [screenCenterX, screenCenterY] = applyToPoint24(transform, [
2342
+ const [screenCenterX, screenCenterY] = applyToPoint27(transform, [
2013
2343
  debugObject.center.x,
2014
2344
  debugObject.center.y
2015
2345
  ]);
@@ -2055,11 +2385,11 @@ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
2055
2385
  ];
2056
2386
  }
2057
2387
  if (debugObject.shape === "line") {
2058
- const [screenStartX, screenStartY] = applyToPoint24(transform, [
2388
+ const [screenStartX, screenStartY] = applyToPoint27(transform, [
2059
2389
  debugObject.start.x,
2060
2390
  debugObject.start.y
2061
2391
  ]);
2062
- const [screenEndX, screenEndY] = applyToPoint24(transform, [
2392
+ const [screenEndX, screenEndY] = applyToPoint27(transform, [
2063
2393
  debugObject.end.x,
2064
2394
  debugObject.end.y
2065
2395
  ]);
@@ -2109,7 +2439,7 @@ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
2109
2439
  }
2110
2440
 
2111
2441
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts
2112
- import { applyToPoint as applyToPoint25 } from "transformation-matrix";
2442
+ import { applyToPoint as applyToPoint28 } from "transformation-matrix";
2113
2443
  function createSchematicTrace(trace, transform) {
2114
2444
  const edges = trace.edges;
2115
2445
  if (edges.length === 0) return [];
@@ -2118,11 +2448,11 @@ function createSchematicTrace(trace, transform) {
2118
2448
  for (let edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
2119
2449
  const edge = edges[edgeIndex];
2120
2450
  if (edge.is_crossing) continue;
2121
- const [screenFromX, screenFromY] = applyToPoint25(transform, [
2451
+ const [screenFromX, screenFromY] = applyToPoint28(transform, [
2122
2452
  edge.from.x,
2123
2453
  edge.from.y
2124
2454
  ]);
2125
- const [screenToX, screenToY] = applyToPoint25(transform, [
2455
+ const [screenToX, screenToY] = applyToPoint28(transform, [
2126
2456
  edge.to.x,
2127
2457
  edge.to.y
2128
2458
  ]);
@@ -2134,11 +2464,11 @@ function createSchematicTrace(trace, transform) {
2134
2464
  }
2135
2465
  for (const edge of edges) {
2136
2466
  if (!edge.is_crossing) continue;
2137
- const [screenFromX, screenFromY] = applyToPoint25(transform, [
2467
+ const [screenFromX, screenFromY] = applyToPoint28(transform, [
2138
2468
  edge.from.x,
2139
2469
  edge.from.y
2140
2470
  ]);
2141
- const [screenToX, screenToY] = applyToPoint25(transform, [
2471
+ const [screenToX, screenToY] = applyToPoint28(transform, [
2142
2472
  edge.to.x,
2143
2473
  edge.to.y
2144
2474
  ]);
@@ -2214,7 +2544,7 @@ function createSchematicTrace(trace, transform) {
2214
2544
  }
2215
2545
  if (trace.junctions) {
2216
2546
  for (const junction of trace.junctions) {
2217
- const [screenX, screenY] = applyToPoint25(transform, [
2547
+ const [screenX, screenY] = applyToPoint28(transform, [
2218
2548
  junction.x,
2219
2549
  junction.y
2220
2550
  ]);
@@ -2247,11 +2577,11 @@ function createSchematicTrace(trace, transform) {
2247
2577
 
2248
2578
  // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
2249
2579
  import {
2250
- applyToPoint as applyToPoint26,
2251
- compose as compose6,
2252
- rotate as rotate3,
2253
- scale as scale3,
2254
- translate as translate6
2580
+ applyToPoint as applyToPoint30,
2581
+ compose as compose8,
2582
+ rotate as rotate4,
2583
+ scale as scale5,
2584
+ translate as translate8
2255
2585
  } from "transformation-matrix";
2256
2586
 
2257
2587
  // lib/sch/arial-text-metrics.ts
@@ -3033,193 +3363,22 @@ var estimateTextWidth = (text) => {
3033
3363
  return totalWidth / 27;
3034
3364
  };
3035
3365
 
3036
- // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
3366
+ // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label-with-symbol.ts
3367
+ import {
3368
+ applyToPoint as applyToPoint29,
3369
+ compose as compose7,
3370
+ rotate as rotate3,
3371
+ scale as scale4,
3372
+ translate as translate7
3373
+ } from "transformation-matrix";
3374
+ import { symbols as symbols3 } from "schematic-symbols";
3375
+
3376
+ // lib/utils/net-label-utils.ts
3377
+ import "transformation-matrix";
3378
+ import "schematic-symbols";
3037
3379
  var ARROW_POINT_WIDTH_FSR = 0.3;
3038
3380
  var END_PADDING_FSR = 0.3;
3039
3381
  var END_PADDING_EXTRA_PER_CHARACTER_FSR = 0.06;
3040
- var createSvgObjectsForSchNetLabel = (schNetLabel, realToScreenTransform) => {
3041
- if (!schNetLabel.text) return [];
3042
- const svgObjects = [];
3043
- const fontSizePx = getSchScreenFontSize(realToScreenTransform, "net_label");
3044
- const fontSizeMm = getSchMmFontSize("net_label");
3045
- const textWidthFSR = estimateTextWidth(schNetLabel.text || "");
3046
- const screenCenter = applyToPoint26(realToScreenTransform, schNetLabel.center);
3047
- const realTextGrowthVec = getUnitVectorFromOutsideToEdge(
3048
- schNetLabel.anchor_side
3049
- );
3050
- const screenTextGrowthVec = { ...realTextGrowthVec };
3051
- screenTextGrowthVec.y *= -1;
3052
- const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + END_PADDING_FSR;
3053
- const screenAnchorPosition = schNetLabel.anchor_position ? applyToPoint26(realToScreenTransform, schNetLabel.anchor_position) : {
3054
- x: screenCenter.x - screenTextGrowthVec.x * fullWidthFsr * fontSizePx / 2,
3055
- y: screenCenter.y - screenTextGrowthVec.y * fullWidthFsr * fontSizePx / 2
3056
- };
3057
- const realAnchorPosition = schNetLabel.anchor_position ?? {
3058
- x: schNetLabel.center.x - realTextGrowthVec.x * fullWidthFsr * fontSizeMm / 2,
3059
- y: schNetLabel.center.y - realTextGrowthVec.y * fullWidthFsr * fontSizeMm / 2
3060
- };
3061
- const pathRotation = {
3062
- left: 0,
3063
- top: -90,
3064
- bottom: 90,
3065
- right: 180
3066
- }[schNetLabel.anchor_side];
3067
- const screenOutlinePoints = [
3068
- // Arrow point in font-relative coordinates
3069
- {
3070
- x: 0,
3071
- y: 0
3072
- },
3073
- // Top left corner in font-relative coordinates
3074
- {
3075
- x: ARROW_POINT_WIDTH_FSR,
3076
- y: 0.6
3077
- },
3078
- // Top right corner in font-relative coordinates
3079
- {
3080
- x: ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_FSR + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + textWidthFSR,
3081
- y: 0.6
3082
- },
3083
- // Bottom right corner in font-relative coordinates
3084
- {
3085
- x: ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_FSR + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + textWidthFSR,
3086
- y: -0.6
3087
- },
3088
- // Bottom left corner in font-relative coordinates
3089
- {
3090
- x: ARROW_POINT_WIDTH_FSR,
3091
- y: -0.6
3092
- }
3093
- ].map(
3094
- (fontRelativePoint) => applyToPoint26(
3095
- compose6(
3096
- realToScreenTransform,
3097
- translate6(realAnchorPosition.x, realAnchorPosition.y),
3098
- scale3(fontSizeMm),
3099
- rotate3(pathRotation / 180 * Math.PI)
3100
- ),
3101
- fontRelativePoint
3102
- )
3103
- );
3104
- const pathD = `
3105
- M ${screenOutlinePoints[0].x},${screenOutlinePoints[0].y}
3106
- L ${screenOutlinePoints[1].x},${screenOutlinePoints[1].y}
3107
- L ${screenOutlinePoints[2].x},${screenOutlinePoints[2].y}
3108
- L ${screenOutlinePoints[3].x},${screenOutlinePoints[3].y}
3109
- L ${screenOutlinePoints[4].x},${screenOutlinePoints[4].y}
3110
- Z
3111
- `;
3112
- svgObjects.push({
3113
- name: "path",
3114
- type: "element",
3115
- attributes: {
3116
- class: "net-label",
3117
- d: pathD,
3118
- fill: "white",
3119
- stroke: colorMap.schematic.label_global,
3120
- "stroke-width": `${getSchStrokeSize(realToScreenTransform)}px`
3121
- },
3122
- value: "",
3123
- children: []
3124
- });
3125
- const screenTextPos = {
3126
- x: screenAnchorPosition.x + screenTextGrowthVec.x * fontSizePx * 0.5,
3127
- y: screenAnchorPosition.y + screenTextGrowthVec.y * fontSizePx * 0.5
3128
- };
3129
- const textAnchor = {
3130
- left: "start",
3131
- top: "start",
3132
- bottom: "start",
3133
- right: "end"
3134
- }[schNetLabel.anchor_side];
3135
- const textTransformString = {
3136
- left: "",
3137
- right: "",
3138
- top: `rotate(90 ${screenTextPos.x} ${screenTextPos.y})`,
3139
- bottom: `rotate(-90 ${screenTextPos.x} ${screenTextPos.y})`
3140
- }[schNetLabel.anchor_side];
3141
- svgObjects.push({
3142
- name: "text",
3143
- type: "element",
3144
- attributes: {
3145
- class: "net-label-text",
3146
- x: screenTextPos.x.toString(),
3147
- y: screenTextPos.y.toString(),
3148
- fill: colorMap.schematic.label_global,
3149
- "text-anchor": textAnchor,
3150
- "dominant-baseline": "central",
3151
- "font-family": "sans-serif",
3152
- "font-variant-numeric": "tabular-nums",
3153
- "font-size": `${fontSizePx}px`,
3154
- transform: textTransformString
3155
- },
3156
- children: [
3157
- {
3158
- type: "text",
3159
- value: schNetLabel.text || "",
3160
- name: "",
3161
- attributes: {},
3162
- children: []
3163
- }
3164
- ],
3165
- value: ""
3166
- });
3167
- return svgObjects;
3168
- };
3169
-
3170
- // lib/sch/svg-object-fns/create-svg-objects-for-sch-text.ts
3171
- import { applyToPoint as applyToPoint27 } from "transformation-matrix";
3172
- var createSvgSchText = (elm, transform) => {
3173
- const center = applyToPoint27(transform, elm.position);
3174
- const textAnchorMap = {
3175
- center: "middle",
3176
- left: "start",
3177
- right: "end",
3178
- top: "middle",
3179
- bottom: "middle"
3180
- };
3181
- const dominantBaselineMap = {
3182
- center: "middle",
3183
- left: "middle",
3184
- right: "middle",
3185
- top: "hanging",
3186
- bottom: "ideographic"
3187
- };
3188
- return {
3189
- type: "element",
3190
- name: "text",
3191
- value: "",
3192
- attributes: {
3193
- x: center.x.toString(),
3194
- y: center.y.toString(),
3195
- fill: elm.color ?? colorMap.schematic.sheet_label,
3196
- "text-anchor": textAnchorMap[elm.anchor],
3197
- "dominant-baseline": dominantBaselineMap[elm.anchor],
3198
- "font-family": "sans-serif",
3199
- "font-size": `${getSchScreenFontSize(transform, "reference_designator")}px`,
3200
- transform: `rotate(${elm.rotation}, ${center.x}, ${center.y})`
3201
- },
3202
- children: [
3203
- {
3204
- type: "text",
3205
- value: elm.text,
3206
- name: elm.schematic_text_id,
3207
- attributes: {},
3208
- children: []
3209
- }
3210
- ]
3211
- };
3212
- };
3213
-
3214
- // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-symbol.ts
3215
- import {
3216
- applyToPoint as applyToPoint28,
3217
- compose as compose7,
3218
- rotate as rotate4,
3219
- scale as scale4,
3220
- translate as translate7
3221
- } from "transformation-matrix";
3222
- import { symbols as symbols3 } from "schematic-symbols";
3223
3382
  var ninePointAnchorToTextAnchor2 = {
3224
3383
  top_left: "start",
3225
3384
  top_right: "end",
@@ -3242,13 +3401,27 @@ var ninePointAnchorToDominantBaseline2 = {
3242
3401
  middle_top: "auto",
3243
3402
  middle_bottom: "hanging"
3244
3403
  };
3245
- var ARROW_POINT_WIDTH_FSR2 = 0.3;
3246
- var END_PADDING_FSR2 = 0.3;
3247
- var END_PADDING_EXTRA_PER_CHARACTER_FSR2 = 0.06;
3248
- var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3404
+ function getTextOffsets(pathRotation, transform) {
3405
+ const scale7 = Math.abs(transform.a);
3406
+ const baseOffset = scale7 * 0.1;
3407
+ const rotationOffsetMap = {
3408
+ "0": { x: baseOffset * 0.8, y: -baseOffset },
3409
+ // Left
3410
+ "-90": { x: baseOffset * 3.3, y: baseOffset * 2.8 },
3411
+ // Top
3412
+ "90": { x: -baseOffset * 3.55, y: -baseOffset * 4.2 },
3413
+ // Bottom
3414
+ "180": { x: -baseOffset * 0.85, y: -baseOffset * 0.2 }
3415
+ // Right
3416
+ };
3417
+ return rotationOffsetMap[pathRotation.toString()] || { x: 0, y: 0 };
3418
+ }
3419
+
3420
+ // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label-with-symbol.ts
3421
+ var createSvgObjectsForSchNetLabelWithSymbol = (schNetLabel, realToScreenTransform) => {
3249
3422
  if (!schNetLabel.text) return [];
3250
3423
  const svgObjects = [];
3251
- const symbol = symbols3["ground_horz"];
3424
+ const symbol = symbols3[schNetLabel.symbol_name];
3252
3425
  if (!symbol) {
3253
3426
  svgObjects.push(
3254
3427
  createSvgSchErrorText({
@@ -3271,7 +3444,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3271
3444
  };
3272
3445
  const fontSizeMm = getSchMmFontSize("net_label");
3273
3446
  const textWidthFSR = estimateTextWidth(schNetLabel.text || "");
3274
- const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR2 * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR2 * schNetLabel.text.length + END_PADDING_FSR2;
3447
+ const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + END_PADDING_FSR;
3275
3448
  const realTextGrowthVec = getUnitVectorFromOutsideToEdge(
3276
3449
  schNetLabel.anchor_side
3277
3450
  );
@@ -3285,7 +3458,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3285
3458
  bottom: 90,
3286
3459
  right: 180
3287
3460
  }[schNetLabel.anchor_side];
3288
- const rotationMatrix = rotate4(pathRotation / 180 * Math.PI);
3461
+ const rotationMatrix = rotate3(pathRotation / 180 * Math.PI);
3289
3462
  const symbolBounds = {
3290
3463
  minX: Math.min(
3291
3464
  ...symbol.primitives.flatMap(
@@ -3312,7 +3485,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3312
3485
  x: symbolBounds.minX,
3313
3486
  y: (symbolBounds.minY + symbolBounds.maxY) / 2
3314
3487
  };
3315
- const rotatedSymbolEnd = applyToPoint28(rotationMatrix, symbolEndPoint);
3488
+ const rotatedSymbolEnd = applyToPoint29(rotationMatrix, symbolEndPoint);
3316
3489
  const symbolToRealTransform = compose7(
3317
3490
  translate7(
3318
3491
  realAnchorPosition.x - rotatedSymbolEnd.x,
@@ -3322,11 +3495,11 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3322
3495
  scale4(1)
3323
3496
  // Use full symbol size
3324
3497
  );
3325
- const [screenMinX, screenMinY] = applyToPoint28(
3498
+ const [screenMinX, screenMinY] = applyToPoint29(
3326
3499
  compose7(realToScreenTransform, symbolToRealTransform),
3327
3500
  [bounds.minX, bounds.minY]
3328
3501
  );
3329
- const [screenMaxX, screenMaxY] = applyToPoint28(
3502
+ const [screenMaxX, screenMaxY] = applyToPoint29(
3330
3503
  compose7(realToScreenTransform, symbolToRealTransform),
3331
3504
  [bounds.maxX, bounds.maxY]
3332
3505
  );
@@ -3350,7 +3523,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3350
3523
  });
3351
3524
  for (const path of symbolPaths) {
3352
3525
  const symbolPath = path.points.map((p, i) => {
3353
- const [x, y] = applyToPoint28(
3526
+ const [x, y] = applyToPoint29(
3354
3527
  compose7(realToScreenTransform, symbolToRealTransform),
3355
3528
  [p.x, p.y]
3356
3529
  );
@@ -3370,7 +3543,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3370
3543
  });
3371
3544
  }
3372
3545
  for (const text of symbolTexts) {
3373
- const screenTextPos = applyToPoint28(
3546
+ const screenTextPos = applyToPoint29(
3374
3547
  compose7(realToScreenTransform, symbolToRealTransform),
3375
3548
  text
3376
3549
  );
@@ -3380,18 +3553,9 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3380
3553
  } else if (textValue === "{VAL}") {
3381
3554
  textValue = "";
3382
3555
  }
3383
- const rotationOffsetMap = {
3384
- "0": { x: 8, y: -10 },
3385
- // Left
3386
- "-90": { x: 33, y: 28 },
3387
- // Top
3388
- "90": { x: -32.5, y: -38 },
3389
- // Bottom
3390
- "180": { x: -8.5, y: -2 }
3391
- // Right
3392
- };
3393
- const currentRotation = pathRotation.toString();
3394
- const rotationOffset = rotationOffsetMap[currentRotation] || { x: 0, y: 0 };
3556
+ const scale7 = Math.abs(realToScreenTransform.a);
3557
+ const baseOffset = scale7 * 0.1;
3558
+ const rotationOffset = getTextOffsets(pathRotation, realToScreenTransform);
3395
3559
  const offsetScreenPos = {
3396
3560
  x: screenTextPos.x + rotationOffset.x,
3397
3561
  y: screenTextPos.y + rotationOffset.y
@@ -3402,7 +3566,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3402
3566
  attributes: {
3403
3567
  x: offsetScreenPos.x.toString(),
3404
3568
  y: offsetScreenPos.y.toString(),
3405
- fill: colorMap.schematic.label_global,
3569
+ fill: colorMap.schematic.label_local,
3406
3570
  "font-family": "sans-serif",
3407
3571
  "text-anchor": ninePointAnchorToTextAnchor2[text.anchor],
3408
3572
  "dominant-baseline": ninePointAnchorToDominantBaseline2[text.anchor],
@@ -3421,7 +3585,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3421
3585
  });
3422
3586
  }
3423
3587
  for (const box of symbolBoxes) {
3424
- const screenBoxPos = applyToPoint28(
3588
+ const screenBoxPos = applyToPoint29(
3425
3589
  compose7(realToScreenTransform, symbolToRealTransform),
3426
3590
  box
3427
3591
  );
@@ -3444,7 +3608,7 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3444
3608
  });
3445
3609
  }
3446
3610
  for (const circle of symbolCircles) {
3447
- const screenCirclePos = applyToPoint28(
3611
+ const screenCirclePos = applyToPoint29(
3448
3612
  compose7(realToScreenTransform, symbolToRealTransform),
3449
3613
  circle
3450
3614
  );
@@ -3470,6 +3634,187 @@ var createSvgObjectsForSchNetSymbol = (schNetLabel, realToScreenTransform) => {
3470
3634
  return svgObjects;
3471
3635
  };
3472
3636
 
3637
+ // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
3638
+ var createSvgObjectsForSchNetLabel = (schNetLabel, realToScreenTransform) => {
3639
+ if (!schNetLabel.text) return [];
3640
+ if (schNetLabel.symbol_name) {
3641
+ return createSvgObjectsForSchNetLabelWithSymbol(
3642
+ schNetLabel,
3643
+ realToScreenTransform
3644
+ );
3645
+ }
3646
+ const svgObjects = [];
3647
+ const fontSizePx = getSchScreenFontSize(realToScreenTransform, "net_label");
3648
+ const fontSizeMm = getSchMmFontSize("net_label");
3649
+ const textWidthFSR = estimateTextWidth(schNetLabel.text || "");
3650
+ const screenCenter = applyToPoint30(realToScreenTransform, schNetLabel.center);
3651
+ const realTextGrowthVec = getUnitVectorFromOutsideToEdge(
3652
+ schNetLabel.anchor_side
3653
+ );
3654
+ const screenTextGrowthVec = { ...realTextGrowthVec };
3655
+ screenTextGrowthVec.y *= -1;
3656
+ const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + END_PADDING_FSR;
3657
+ const screenAnchorPosition = schNetLabel.anchor_position ? applyToPoint30(realToScreenTransform, schNetLabel.anchor_position) : {
3658
+ x: screenCenter.x - screenTextGrowthVec.x * fullWidthFsr * fontSizePx / 2,
3659
+ y: screenCenter.y - screenTextGrowthVec.y * fullWidthFsr * fontSizePx / 2
3660
+ };
3661
+ const realAnchorPosition = schNetLabel.anchor_position ?? {
3662
+ x: schNetLabel.center.x - realTextGrowthVec.x * fullWidthFsr * fontSizeMm / 2,
3663
+ y: schNetLabel.center.y - realTextGrowthVec.y * fullWidthFsr * fontSizeMm / 2
3664
+ };
3665
+ const pathRotation = {
3666
+ left: 0,
3667
+ top: -90,
3668
+ bottom: 90,
3669
+ right: 180
3670
+ }[schNetLabel.anchor_side];
3671
+ const screenOutlinePoints = [
3672
+ // Arrow point in font-relative coordinates
3673
+ {
3674
+ x: 0,
3675
+ y: 0
3676
+ },
3677
+ // Top left corner in font-relative coordinates
3678
+ {
3679
+ x: ARROW_POINT_WIDTH_FSR,
3680
+ y: 0.6
3681
+ },
3682
+ // Top right corner in font-relative coordinates
3683
+ {
3684
+ x: ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_FSR + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + textWidthFSR,
3685
+ y: 0.6
3686
+ },
3687
+ // Bottom right corner in font-relative coordinates
3688
+ {
3689
+ x: ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_FSR + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + textWidthFSR,
3690
+ y: -0.6
3691
+ },
3692
+ // Bottom left corner in font-relative coordinates
3693
+ {
3694
+ x: ARROW_POINT_WIDTH_FSR,
3695
+ y: -0.6
3696
+ }
3697
+ ].map(
3698
+ (fontRelativePoint) => applyToPoint30(
3699
+ compose8(
3700
+ realToScreenTransform,
3701
+ translate8(realAnchorPosition.x, realAnchorPosition.y),
3702
+ scale5(fontSizeMm),
3703
+ rotate4(pathRotation / 180 * Math.PI)
3704
+ ),
3705
+ fontRelativePoint
3706
+ )
3707
+ );
3708
+ const pathD = `
3709
+ M ${screenOutlinePoints[0].x},${screenOutlinePoints[0].y}
3710
+ L ${screenOutlinePoints[1].x},${screenOutlinePoints[1].y}
3711
+ L ${screenOutlinePoints[2].x},${screenOutlinePoints[2].y}
3712
+ L ${screenOutlinePoints[3].x},${screenOutlinePoints[3].y}
3713
+ L ${screenOutlinePoints[4].x},${screenOutlinePoints[4].y}
3714
+ Z
3715
+ `;
3716
+ svgObjects.push({
3717
+ name: "path",
3718
+ type: "element",
3719
+ attributes: {
3720
+ class: "net-label",
3721
+ d: pathD,
3722
+ fill: "white",
3723
+ stroke: colorMap.schematic.label_global,
3724
+ "stroke-width": `${getSchStrokeSize(realToScreenTransform)}px`
3725
+ },
3726
+ value: "",
3727
+ children: []
3728
+ });
3729
+ const screenTextPos = {
3730
+ x: screenAnchorPosition.x + screenTextGrowthVec.x * fontSizePx * 0.5,
3731
+ y: screenAnchorPosition.y + screenTextGrowthVec.y * fontSizePx * 0.5
3732
+ };
3733
+ const textAnchor = {
3734
+ left: "start",
3735
+ top: "start",
3736
+ bottom: "start",
3737
+ right: "end"
3738
+ }[schNetLabel.anchor_side];
3739
+ const textTransformString = {
3740
+ left: "",
3741
+ right: "",
3742
+ top: `rotate(90 ${screenTextPos.x} ${screenTextPos.y})`,
3743
+ bottom: `rotate(-90 ${screenTextPos.x} ${screenTextPos.y})`
3744
+ }[schNetLabel.anchor_side];
3745
+ svgObjects.push({
3746
+ name: "text",
3747
+ type: "element",
3748
+ attributes: {
3749
+ class: "net-label-text",
3750
+ x: screenTextPos.x.toString(),
3751
+ y: screenTextPos.y.toString(),
3752
+ fill: colorMap.schematic.label_global,
3753
+ "text-anchor": textAnchor,
3754
+ "dominant-baseline": "central",
3755
+ "font-family": "sans-serif",
3756
+ "font-variant-numeric": "tabular-nums",
3757
+ "font-size": `${fontSizePx}px`,
3758
+ transform: textTransformString
3759
+ },
3760
+ children: [
3761
+ {
3762
+ type: "text",
3763
+ value: schNetLabel.text || "",
3764
+ name: "",
3765
+ attributes: {},
3766
+ children: []
3767
+ }
3768
+ ],
3769
+ value: ""
3770
+ });
3771
+ return svgObjects;
3772
+ };
3773
+
3774
+ // lib/sch/svg-object-fns/create-svg-objects-for-sch-text.ts
3775
+ import { applyToPoint as applyToPoint31 } from "transformation-matrix";
3776
+ var createSvgSchText = (elm, transform) => {
3777
+ const center = applyToPoint31(transform, elm.position);
3778
+ const textAnchorMap = {
3779
+ center: "middle",
3780
+ left: "start",
3781
+ right: "end",
3782
+ top: "middle",
3783
+ bottom: "middle"
3784
+ };
3785
+ const dominantBaselineMap = {
3786
+ center: "middle",
3787
+ left: "middle",
3788
+ right: "middle",
3789
+ top: "hanging",
3790
+ bottom: "ideographic"
3791
+ };
3792
+ return {
3793
+ type: "element",
3794
+ name: "text",
3795
+ value: "",
3796
+ attributes: {
3797
+ x: center.x.toString(),
3798
+ y: center.y.toString(),
3799
+ fill: elm.color ?? colorMap.schematic.sheet_label,
3800
+ "text-anchor": textAnchorMap[elm.anchor],
3801
+ "dominant-baseline": dominantBaselineMap[elm.anchor],
3802
+ "font-family": "sans-serif",
3803
+ "font-size": `${getSchScreenFontSize(transform, "reference_designator")}px`,
3804
+ transform: `rotate(${elm.rotation}, ${center.x}, ${center.y})`
3805
+ },
3806
+ children: [
3807
+ {
3808
+ type: "text",
3809
+ value: elm.text,
3810
+ name: elm.schematic_text_id,
3811
+ attributes: {},
3812
+ children: []
3813
+ }
3814
+ ]
3815
+ };
3816
+ };
3817
+
3473
3818
  // lib/sch/convert-circuit-json-to-schematic-svg.ts
3474
3819
  function convertCircuitJsonToSchematicSvg(circuitJson, options) {
3475
3820
  const realBounds = getSchematicBoundsFromCircuitJson(circuitJson);
@@ -3547,7 +3892,7 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
3547
3892
  } else if (elm.type === "schematic_trace") {
3548
3893
  schTraceSvgs.push(...createSchematicTrace(elm, transform));
3549
3894
  } else if (elm.type === "schematic_net_label") {
3550
- elm.symbol_name ? schNetLabel.push(...createSvgObjectsForSchNetSymbol(elm, transform)) : schNetLabel.push(...createSvgObjectsForSchNetLabel(elm, transform));
3895
+ schNetLabel.push(...createSvgObjectsForSchNetLabel(elm, transform));
3551
3896
  } else if (elm.type === "schematic_text") {
3552
3897
  schText.push(createSvgSchText(elm, transform));
3553
3898
  } else if (elm.type === "schematic_voltage_probe") {
@@ -3620,12 +3965,13 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
3620
3965
  ],
3621
3966
  value: ""
3622
3967
  };
3623
- return stringify2(svgObject);
3968
+ return stringify3(svgObject);
3624
3969
  }
3625
3970
  var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
3626
3971
  export {
3627
3972
  circuitJsonToPcbSvg,
3628
3973
  circuitJsonToSchematicSvg,
3974
+ convertCircuitJsonToAssemblySvg,
3629
3975
  convertCircuitJsonToPcbSvg,
3630
3976
  convertCircuitJsonToSchematicSvg
3631
3977
  };