circuit-to-svg 0.0.49 → 0.0.50

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
@@ -976,82 +976,55 @@ var colorMap = {
976
976
  }
977
977
  };
978
978
 
979
- // lib/sch/get-schematic-bounds-from-circuit-json.ts
980
- function getSchematicBoundsFromCircuitJson(soup, padding = 0.5) {
981
- let minX = Number.POSITIVE_INFINITY;
982
- let minY = Number.POSITIVE_INFINITY;
983
- let maxX = Number.NEGATIVE_INFINITY;
984
- let maxY = Number.NEGATIVE_INFINITY;
985
- const portSize = 0.2;
986
- for (const item of soup) {
987
- if (item.type === "schematic_component") {
988
- updateBounds(item.center, item.size, item.rotation || 0);
989
- } else if (item.type === "schematic_port") {
990
- updateBounds(item.center, { width: portSize, height: portSize }, 0);
991
- } else if (item.type === "schematic_debug_object") {
992
- if (item.shape === "rect") {
993
- updateBounds(item.center, item.size, 0);
994
- } else if (item.shape === "line") {
995
- updateBounds(item.start, { width: 0.1, height: 0.1 }, 0);
996
- updateBounds(item.end, { width: 0.1, height: 0.1 }, 0);
997
- }
998
- }
999
- }
1000
- minX -= padding;
1001
- minY -= padding;
1002
- maxX += padding;
1003
- maxY += padding;
1004
- return { minX, minY, maxX, maxY };
1005
- function updateBounds(center, size, rotation) {
1006
- const corners = [
1007
- { x: -size.width / 2, y: -size.height / 2 },
1008
- { x: size.width / 2, y: -size.height / 2 },
1009
- { x: size.width / 2, y: size.height / 2 },
1010
- { x: -size.width / 2, y: size.height / 2 }
1011
- ];
1012
- for (const corner of corners) {
1013
- const rotatedX = corner.x * Math.cos(rotation) - corner.y * Math.sin(rotation) + center.x;
1014
- const rotatedY = corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + center.y;
1015
- minX = Math.min(minX, rotatedX);
1016
- minY = Math.min(minY, rotatedY);
1017
- maxX = Math.max(maxX, rotatedX);
1018
- maxY = Math.max(maxY, rotatedY);
1019
- }
1020
- }
1021
- }
979
+ // lib/sch/convert-circuit-json-to-schematic-svg.ts
980
+ import { stringify as stringify2 } from "svgson";
981
+ import {
982
+ compose as compose4,
983
+ scale as scale2,
984
+ translate as translate4
985
+ } from "transformation-matrix";
1022
986
 
1023
987
  // lib/sch/draw-schematic-grid.ts
988
+ import { applyToPoint as applyToPoint12 } from "transformation-matrix";
1024
989
  function drawSchematicGrid(params) {
1025
990
  const { minX, minY, maxX, maxY } = params.bounds;
1026
991
  const cellSize = params.cellSize ?? 1;
1027
992
  const labelCells = params.labelCells ?? false;
1028
993
  const gridLines = [];
994
+ const transformPoint = (x, y) => {
995
+ const [transformedX, transformedY] = applyToPoint12(params.transform, [x, y]);
996
+ return { x: transformedX, y: transformedY };
997
+ };
1029
998
  for (let x = Math.ceil(minX); x <= Math.floor(maxX); x += cellSize) {
999
+ const start = transformPoint(x, minY);
1000
+ const end = transformPoint(x, maxY);
1030
1001
  gridLines.push({
1031
1002
  name: "line",
1032
1003
  type: "element",
1033
1004
  attributes: {
1034
- x1: x.toString(),
1035
- y1: minY.toString(),
1036
- x2: x.toString(),
1037
- y2: maxY.toString(),
1005
+ x1: start.x.toString(),
1006
+ y1: start.y.toString(),
1007
+ x2: end.x.toString(),
1008
+ y2: end.y.toString(),
1038
1009
  stroke: colorMap.schematic.grid,
1039
- "stroke-width": "0.01",
1010
+ "stroke-width": (0.01 * Math.abs(params.transform.a)).toString(),
1040
1011
  "stroke-opacity": "0.5"
1041
1012
  }
1042
1013
  });
1043
1014
  }
1044
1015
  for (let y = Math.ceil(minY); y <= Math.floor(maxY); y += cellSize) {
1016
+ const start = transformPoint(minX, y);
1017
+ const end = transformPoint(maxX, y);
1045
1018
  gridLines.push({
1046
1019
  name: "line",
1047
1020
  type: "element",
1048
1021
  attributes: {
1049
- x1: minX.toString(),
1050
- y1: y.toString(),
1051
- x2: maxX.toString(),
1052
- y2: y.toString(),
1022
+ x1: start.x.toString(),
1023
+ y1: start.y.toString(),
1024
+ x2: end.x.toString(),
1025
+ y2: end.y.toString(),
1053
1026
  stroke: colorMap.schematic.grid,
1054
- "stroke-width": "0.01",
1027
+ "stroke-width": (0.01 * Math.abs(params.transform.a)).toString(),
1055
1028
  "stroke-opacity": "0.5"
1056
1029
  }
1057
1030
  });
@@ -1059,15 +1032,18 @@ function drawSchematicGrid(params) {
1059
1032
  if (labelCells) {
1060
1033
  for (let x = Math.ceil(minX); x <= Math.floor(maxX); x += cellSize) {
1061
1034
  for (let y = Math.ceil(minY); y <= Math.floor(maxY); y += cellSize) {
1035
+ const point = transformPoint(x, y);
1062
1036
  gridLines.push({
1063
1037
  name: "text",
1064
1038
  type: "element",
1065
1039
  attributes: {
1066
- x: x.toString(),
1067
- y: y.toString(),
1040
+ x: point.x.toString(),
1041
+ y: point.y.toString(),
1068
1042
  fill: colorMap.schematic.grid,
1069
- "font-size": (cellSize / 6).toString(),
1070
- "fill-opacity": "0.5"
1043
+ "font-size": (cellSize / 6 * Math.abs(params.transform.a)).toString(),
1044
+ "fill-opacity": "0.5",
1045
+ "text-anchor": "middle",
1046
+ "dominant-baseline": "middle"
1071
1047
  },
1072
1048
  children: [
1073
1049
  {
@@ -1092,29 +1068,40 @@ function drawSchematicGrid(params) {
1092
1068
  }
1093
1069
 
1094
1070
  // lib/sch/draw-schematic-labeled-points.ts
1071
+ import { applyToPoint as applyToPoint13 } from "transformation-matrix";
1095
1072
  function drawSchematicLabeledPoints(params) {
1096
1073
  const { points, transform } = params;
1097
1074
  const labeledPointsGroup = [];
1098
1075
  for (const point of points) {
1076
+ const [x1, y1] = applyToPoint13(transform, [point.x - 0.1, -(point.y - 0.1)]);
1077
+ const [x2, y2] = applyToPoint13(transform, [point.x + 0.1, -(point.y + 0.1)]);
1078
+ const [x3, y3] = applyToPoint13(transform, [point.x - 0.1, -(point.y + 0.1)]);
1079
+ const [x4, y4] = applyToPoint13(transform, [point.x + 0.1, -(point.y - 0.1)]);
1099
1080
  labeledPointsGroup.push({
1100
1081
  name: "path",
1101
1082
  type: "element",
1102
1083
  attributes: {
1103
- d: `M${point.x - 0.1},${point.y - 0.1} L${point.x + 0.1},${point.y + 0.1} M${point.x - 0.1},${point.y + 0.1} L${point.x + 0.1},${point.y - 0.1}`,
1084
+ d: `M${x1},${y1} L${x2},${y2} M${x3},${y3} L${x4},${y4}`,
1104
1085
  stroke: colorMap.schematic.grid,
1105
- "stroke-width": "0.02",
1086
+ "stroke-width": (0.02 * Math.abs(transform.a)).toString(),
1106
1087
  "stroke-opacity": "0.7"
1107
1088
  }
1108
1089
  });
1090
+ const [labelX, labelY] = applyToPoint13(transform, [
1091
+ point.x + 0.15,
1092
+ -(point.y - 0.15)
1093
+ ]);
1109
1094
  labeledPointsGroup.push({
1110
1095
  name: "text",
1111
1096
  type: "element",
1112
1097
  attributes: {
1113
- x: (point.x + 0.15).toString(),
1114
- y: (point.y - 0.15).toString(),
1098
+ x: labelX.toString(),
1099
+ y: labelY.toString(),
1115
1100
  fill: colorMap.schematic.grid,
1116
- "font-size": "0.15",
1117
- "fill-opacity": "0.7"
1101
+ "font-size": (0.15 * Math.abs(transform.a)).toString(),
1102
+ "fill-opacity": "0.7",
1103
+ "text-anchor": "start",
1104
+ "dominant-baseline": "middle"
1118
1105
  },
1119
1106
  children: [
1120
1107
  {
@@ -1136,25 +1123,70 @@ function drawSchematicLabeledPoints(params) {
1136
1123
  };
1137
1124
  }
1138
1125
 
1139
- // lib/sch/convert-circuit-json-to-schematic-svg.ts
1140
- import { stringify as stringify2 } from "svgson";
1126
+ // lib/sch/get-schematic-bounds-from-circuit-json.ts
1127
+ function getSchematicBoundsFromCircuitJson(soup, padding = 0.5) {
1128
+ let minX = Number.POSITIVE_INFINITY;
1129
+ let minY = Number.POSITIVE_INFINITY;
1130
+ let maxX = Number.NEGATIVE_INFINITY;
1131
+ let maxY = Number.NEGATIVE_INFINITY;
1132
+ const portSize = 0.2;
1133
+ for (const item of soup) {
1134
+ if (item.type === "schematic_component") {
1135
+ updateBounds(item.center, item.size, item.rotation || 0);
1136
+ } else if (item.type === "schematic_port") {
1137
+ updateBounds(item.center, { width: portSize, height: portSize }, 0);
1138
+ } else if (item.type === "schematic_debug_object") {
1139
+ if (item.shape === "rect") {
1140
+ updateBounds(item.center, item.size, 0);
1141
+ } else if (item.shape === "line") {
1142
+ updateBounds(item.start, { width: 0.1, height: 0.1 }, 0);
1143
+ updateBounds(item.end, { width: 0.1, height: 0.1 }, 0);
1144
+ }
1145
+ }
1146
+ }
1147
+ minX -= padding;
1148
+ minY -= padding;
1149
+ maxX += padding;
1150
+ maxY += padding;
1151
+ return { minX, minY, maxX, maxY };
1152
+ function updateBounds(center, size, rotation) {
1153
+ const corners = [
1154
+ { x: -size.width / 2, y: -size.height / 2 },
1155
+ { x: size.width / 2, y: -size.height / 2 },
1156
+ { x: size.width / 2, y: size.height / 2 },
1157
+ { x: -size.width / 2, y: size.height / 2 }
1158
+ ];
1159
+ for (const corner of corners) {
1160
+ const rotatedX = corner.x * Math.cos(rotation) - corner.y * Math.sin(rotation) + center.x;
1161
+ const rotatedY = corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + center.y;
1162
+ minX = Math.min(minX, rotatedX);
1163
+ minY = Math.min(minY, rotatedY);
1164
+ maxX = Math.max(maxX, rotatedX);
1165
+ maxY = Math.max(maxY, rotatedY);
1166
+ }
1167
+ }
1168
+ }
1141
1169
 
1142
1170
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-component.ts
1143
1171
  import { getSvg, symbols } from "schematic-symbols";
1144
1172
  import { parseSync } from "svgson";
1173
+ import { applyToPoint as applyToPoint14 } from "transformation-matrix";
1145
1174
  function createSchematicComponent({
1146
1175
  component,
1176
+ transform,
1147
1177
  circuitJson
1148
1178
  }) {
1149
- const center = component.center;
1150
- const size = component.size;
1151
- const rotation = component.rotation;
1152
- const symbolName = component.symbol_name;
1179
+ const { center, size, rotation, symbol_name: symbolName } = component;
1153
1180
  const portLabels = component.port_labels;
1154
1181
  const sourceComponentId = component.source_component_id;
1155
1182
  const schematicComponentId = component.schematic_component_id;
1156
- const transformString = `translate(${center.x}, ${center.y}) rotate(${rotation * 180 / Math.PI})`;
1157
- let children = [];
1183
+ const [transformedX, transformedY] = applyToPoint14(transform, [
1184
+ center.x,
1185
+ center.y
1186
+ ]);
1187
+ const componentScale = Math.abs(transform.a);
1188
+ let componentChildren = [];
1189
+ const textChildren = [];
1158
1190
  const sourceComponent = circuitJson?.find(
1159
1191
  (item) => item.type === "source_component" && item.source_component_id === sourceComponentId
1160
1192
  );
@@ -1175,24 +1207,75 @@ function createSchematicComponent({
1175
1207
  height: size.height
1176
1208
  })
1177
1209
  );
1178
- children = svg.children.filter(
1210
+ componentChildren = svg.children.filter(
1179
1211
  (child) => child.name === "path" && child.attributes.fill !== "green"
1180
1212
  ).map((path) => {
1181
1213
  const currentStrokeWidth = Number.parseFloat(
1182
1214
  path.attributes["stroke-width"] || "0.02"
1183
1215
  );
1184
- const newStrokeWidth = (currentStrokeWidth * 1.5).toString();
1185
1216
  return {
1186
1217
  ...path,
1187
1218
  attributes: {
1188
1219
  ...path.attributes,
1189
1220
  stroke: path.attributes.stroke === "black" ? `${colorMap.schematic.component_outline}` : path.attributes.stroke,
1190
- "stroke-width": newStrokeWidth
1221
+ "stroke-width": currentStrokeWidth.toString()
1191
1222
  }
1192
1223
  };
1193
1224
  });
1225
+ if (resistance || capacitance) {
1226
+ const [textX, textY] = applyToPoint14(transform, [
1227
+ center.x,
1228
+ -(center.y - size.height / 2 - 0.2)
1229
+ ]);
1230
+ const labelOffset = componentScale * 0.4;
1231
+ console.log(labelOffset);
1232
+ textChildren.push({
1233
+ name: "text",
1234
+ type: "element",
1235
+ attributes: {
1236
+ class: "component-name",
1237
+ x: textX.toString(),
1238
+ y: textY.toString(),
1239
+ "text-anchor": "middle",
1240
+ "dominant-baseline": "auto",
1241
+ "font-size": "0.2"
1242
+ },
1243
+ children: [
1244
+ {
1245
+ type: "text",
1246
+ value: (resistance || capacitance || "").toString(),
1247
+ name: "",
1248
+ attributes: {},
1249
+ children: []
1250
+ }
1251
+ ],
1252
+ value: ""
1253
+ });
1254
+ textChildren.push({
1255
+ name: "text",
1256
+ type: "element",
1257
+ attributes: {
1258
+ class: "component-name",
1259
+ x: textX.toString(),
1260
+ y: (textY - labelOffset).toString(),
1261
+ "text-anchor": "middle",
1262
+ "dominant-baseline": "auto",
1263
+ "font-size": "0.2"
1264
+ },
1265
+ children: [
1266
+ {
1267
+ type: "text",
1268
+ value: componentName || "",
1269
+ name: "",
1270
+ attributes: {},
1271
+ children: []
1272
+ }
1273
+ ],
1274
+ value: ""
1275
+ });
1276
+ }
1194
1277
  } else {
1195
- children.push({
1278
+ componentChildren.push({
1196
1279
  name: "rect",
1197
1280
  type: "element",
1198
1281
  value: "",
@@ -1201,20 +1284,30 @@ function createSchematicComponent({
1201
1284
  x: (-size.width / 2).toString(),
1202
1285
  y: (-size.height / 2).toString(),
1203
1286
  width: size.width.toString(),
1204
- height: size.height.toString()
1287
+ height: size.height.toString(),
1288
+ "stroke-width": "0.02"
1205
1289
  },
1206
1290
  children: []
1207
1291
  });
1208
1292
  if (manufacturerNumber) {
1209
- children.push({
1293
+ const [textX, textY] = applyToPoint14(transform, [
1294
+ center.x,
1295
+ // Center X position
1296
+ -(center.y - size.height / 2 - 0.5)
1297
+ // Above the component top edge
1298
+ ]);
1299
+ const labelOffset = componentScale * 0.4;
1300
+ textChildren.push({
1210
1301
  name: "text",
1211
1302
  type: "element",
1212
1303
  attributes: {
1213
1304
  class: "component-name",
1214
- x: 1.2.toString(),
1215
- y: (-size.height / 2 - 0.5).toString(),
1305
+ x: textX.toString(),
1306
+ y: textY.toString(),
1216
1307
  "text-anchor": "right",
1217
- "dominant-baseline": "auto"
1308
+ // Center align text
1309
+ "dominant-baseline": "auto",
1310
+ "font-size": "0.2"
1218
1311
  },
1219
1312
  children: [
1220
1313
  {
@@ -1227,15 +1320,17 @@ function createSchematicComponent({
1227
1320
  ],
1228
1321
  value: ""
1229
1322
  });
1230
- children.push({
1323
+ textChildren.push({
1231
1324
  name: "text",
1232
1325
  type: "element",
1233
1326
  attributes: {
1234
1327
  class: "component-name",
1235
- x: 1.2.toString(),
1236
- y: (-size.height / 2 - 0.7).toString(),
1328
+ x: textX.toString(),
1329
+ y: (textY - labelOffset).toString(),
1237
1330
  "text-anchor": "right",
1238
- "dominant-baseline": "auto"
1331
+ // Center align text
1332
+ "dominant-baseline": "auto",
1333
+ "font-size": "0.2"
1239
1334
  },
1240
1335
  children: [
1241
1336
  {
@@ -1256,64 +1351,81 @@ function createSchematicComponent({
1256
1351
  const circleRadius = 0.05;
1257
1352
  for (const port of schematicPorts) {
1258
1353
  const { x: portX, y: portY, pinNumber } = port.center;
1259
- const x = portX - center.x;
1260
- const y = portY - center.y;
1261
- let endX = x;
1262
- let endY = y;
1263
- let labelX = x;
1264
- let labelY = y;
1265
- let textAnchor = "middle";
1266
- let dominantBaseline = "middle";
1354
+ const relX = portX - center.x;
1355
+ const relY = portY - center.y;
1356
+ let endX = relX;
1357
+ let endY = relY;
1267
1358
  switch (port.center.side) {
1268
1359
  case "left":
1269
- endX = x - portLength;
1270
- labelX = x + 0.2;
1271
- textAnchor = "start";
1360
+ endX = relX - portLength;
1272
1361
  break;
1273
1362
  case "right":
1274
- endX = x + portLength;
1275
- labelX = x - 0.2;
1276
- textAnchor = "end";
1363
+ endX = relX + portLength;
1277
1364
  break;
1278
1365
  case "top":
1279
- endY = y - portLength;
1280
- labelY = y - 0.2;
1281
- dominantBaseline = "hanging";
1366
+ endY = relY - portLength;
1282
1367
  break;
1283
1368
  case "bottom":
1284
- endY = y + portLength;
1285
- labelY = y + 0.2;
1286
- dominantBaseline = "auto";
1369
+ endY = relY + portLength;
1287
1370
  break;
1288
1371
  }
1289
- children.push({
1372
+ componentChildren.push({
1290
1373
  name: "line",
1291
1374
  type: "element",
1292
1375
  attributes: {
1293
1376
  class: "component-pin",
1294
- x1: x.toString(),
1295
- y1: y.toString(),
1377
+ x1: relX.toString(),
1378
+ y1: relY.toString(),
1296
1379
  x2: endX.toString(),
1297
- y2: endY.toString()
1380
+ y2: endY.toString(),
1381
+ "stroke-width": "0.02"
1298
1382
  },
1299
1383
  value: "",
1300
1384
  children: []
1301
1385
  });
1302
- children.push({
1386
+ componentChildren.push({
1303
1387
  name: "circle",
1304
1388
  type: "element",
1305
1389
  attributes: {
1306
1390
  class: "component-pin",
1307
1391
  cx: endX.toString(),
1308
1392
  cy: endY.toString(),
1309
- r: circleRadius.toString()
1393
+ r: circleRadius.toString(),
1394
+ "stroke-width": "0.02"
1310
1395
  },
1311
1396
  value: "",
1312
1397
  children: []
1313
1398
  });
1399
+ const [portEndX, portEndY] = applyToPoint14(transform, [
1400
+ center.x + endX,
1401
+ center.y + endY
1402
+ ]);
1314
1403
  const labelKey = `pin${pinNumber}`;
1315
1404
  if (portLabels && labelKey in portLabels) {
1316
- children.push({
1405
+ const labelText = portLabels[labelKey];
1406
+ let labelX = portEndX;
1407
+ let labelY = portEndY;
1408
+ let textAnchor = "middle";
1409
+ const labelOffset = 0.6 * componentScale;
1410
+ switch (port.center.side) {
1411
+ case "left":
1412
+ labelX += labelOffset;
1413
+ labelY += 0;
1414
+ textAnchor = "start";
1415
+ break;
1416
+ case "right":
1417
+ labelX -= labelOffset;
1418
+ labelY += 0;
1419
+ textAnchor = "end";
1420
+ break;
1421
+ case "top":
1422
+ labelY -= labelOffset;
1423
+ break;
1424
+ case "bottom":
1425
+ labelY += labelOffset;
1426
+ break;
1427
+ }
1428
+ textChildren.push({
1317
1429
  name: "text",
1318
1430
  type: "element",
1319
1431
  attributes: {
@@ -1321,13 +1433,13 @@ function createSchematicComponent({
1321
1433
  x: labelX.toString(),
1322
1434
  y: labelY.toString(),
1323
1435
  "text-anchor": textAnchor,
1324
- "dominant-baseline": dominantBaseline,
1325
- "font-size": "0.2"
1436
+ "dominant-baseline": "middle",
1437
+ "font-size": (0.2 * componentScale).toString()
1326
1438
  },
1327
1439
  children: [
1328
1440
  {
1329
1441
  type: "text",
1330
- value: portLabels[labelKey],
1442
+ value: labelText,
1331
1443
  name: "",
1332
1444
  attributes: {},
1333
1445
  children: []
@@ -1336,36 +1448,47 @@ function createSchematicComponent({
1336
1448
  value: ""
1337
1449
  });
1338
1450
  }
1339
- const pinNumberX = endX;
1340
- let pinNumberY = endY;
1341
- const pinNumberAnchor = "middle";
1342
- let pinNumberBaseline = "middle";
1451
+ const pinNumberOffset = 0.2;
1452
+ let pinX = endX;
1453
+ let pinY = endY;
1454
+ let dominantBaseline = "auto";
1343
1455
  switch (port.center.side) {
1344
- case "left":
1345
- case "right":
1346
- pinNumberY -= 0.15;
1347
- break;
1348
1456
  case "top":
1349
- pinNumberY -= 0.15;
1350
- pinNumberBaseline = "auto";
1457
+ pinY = -(portY - portLength - pinNumberOffset);
1458
+ pinX = portX;
1459
+ dominantBaseline = "auto";
1351
1460
  break;
1352
1461
  case "bottom":
1353
- pinNumberY += 0.15;
1354
- pinNumberBaseline = "hanging";
1462
+ pinY = portY + portLength + pinNumberOffset;
1463
+ pinX = portX;
1464
+ dominantBaseline = "hanging";
1465
+ break;
1466
+ case "left":
1467
+ pinX = portX - pinNumberOffset;
1468
+ pinY = portY + pinNumberOffset;
1469
+ dominantBaseline = "auto";
1470
+ break;
1471
+ case "right":
1472
+ pinX = portX + pinNumberOffset;
1473
+ pinY = portY + pinNumberOffset;
1474
+ dominantBaseline = "auto";
1355
1475
  break;
1356
1476
  }
1357
- children.push({
1477
+ const [transformedPinX, transformedPinY] = applyToPoint14(transform, [
1478
+ pinX,
1479
+ pinY
1480
+ ]);
1481
+ textChildren.push({
1358
1482
  name: "text",
1359
1483
  type: "element",
1360
1484
  attributes: {
1361
1485
  class: "pin-number",
1362
- x: pinNumberX.toString(),
1363
- y: pinNumberY.toString(),
1364
- "text-anchor": pinNumberAnchor,
1365
- "dominant-baseline": pinNumberBaseline,
1366
- "font-size": "0.15"
1486
+ x: transformedPinX.toString(),
1487
+ y: transformedPinY.toString(),
1488
+ "text-anchor": "middle",
1489
+ "dominant-baseline": dominantBaseline,
1490
+ "font-size": (0.15 * componentScale).toString()
1367
1491
  },
1368
- value: "",
1369
1492
  children: [
1370
1493
  {
1371
1494
  type: "text",
@@ -1374,82 +1497,62 @@ function createSchematicComponent({
1374
1497
  attributes: {},
1375
1498
  children: []
1376
1499
  }
1377
- ]
1500
+ ],
1501
+ value: ""
1378
1502
  });
1379
1503
  }
1380
1504
  }
1381
- if (resistance || capacitance) {
1382
- children.push({
1383
- name: "text",
1384
- type: "element",
1385
- attributes: {
1386
- class: "component-name",
1387
- x: "0",
1388
- y: (-size.height / 2 - 0.2).toString(),
1389
- "text-anchor": "middle",
1390
- "dominant-baseline": "auto"
1391
- },
1392
- value: "",
1393
- children: [
1394
- {
1395
- type: "text",
1396
- value: (resistance || capacitance || "").toString(),
1397
- name: "",
1398
- attributes: {},
1399
- children: []
1400
- }
1401
- ]
1402
- });
1403
- children.push({
1404
- name: "text",
1405
- type: "element",
1406
- attributes: {
1407
- class: "component-name",
1408
- x: "0",
1409
- y: (-size.height / 2 - 0.5).toString(),
1410
- "text-anchor": "middle",
1411
- "dominant-baseline": "auto"
1412
- },
1413
- value: "",
1414
- children: [
1415
- {
1416
- type: "text",
1417
- value: componentName || "",
1418
- name: "",
1419
- attributes: {},
1420
- children: []
1421
- }
1422
- ]
1423
- });
1424
- }
1425
- return [
1426
- {
1427
- name: "g",
1428
- value: "",
1429
- type: "element",
1430
- attributes: { transform: transformString },
1431
- children
1432
- }
1433
- ];
1505
+ const componentGroup = {
1506
+ name: "g",
1507
+ value: "",
1508
+ type: "element",
1509
+ attributes: {
1510
+ transform: `translate(${transformedX}, ${transformedY}) rotate(${rotation * 180 / Math.PI}) scale(${componentScale})`
1511
+ },
1512
+ children: componentChildren
1513
+ };
1514
+ const textGroup = {
1515
+ name: "g",
1516
+ value: "",
1517
+ type: "element",
1518
+ attributes: {},
1519
+ children: textChildren
1520
+ };
1521
+ return [componentGroup, textGroup];
1434
1522
  }
1435
1523
 
1436
1524
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-debug-object.ts
1437
- function createSvgObjectsFromSchDebugObject(debugObject) {
1525
+ import { applyToPoint as applyToPoint15 } from "transformation-matrix";
1526
+ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
1438
1527
  if (debugObject.shape === "rect") {
1528
+ const x = debugObject.center.x - debugObject.size.width / 2;
1529
+ const y = -(debugObject.center.y - debugObject.size.height / 2);
1530
+ const [transformedX, transformedY] = applyToPoint15(transform, [x, y]);
1531
+ const [transformedRight, transformedBottom] = applyToPoint15(transform, [
1532
+ x + debugObject.size.width,
1533
+ y - debugObject.size.height
1534
+ // Flip height direction
1535
+ ]);
1536
+ const width = Math.abs(transformedRight - transformedX);
1537
+ const height = Math.abs(transformedBottom - transformedY);
1538
+ const [centerX, centerY] = applyToPoint15(transform, [
1539
+ debugObject.center.x,
1540
+ -debugObject.center.y
1541
+ ]);
1439
1542
  return [
1440
1543
  {
1441
1544
  name: "rect",
1442
1545
  type: "element",
1443
1546
  value: "",
1444
1547
  attributes: {
1445
- x: (debugObject.center.x - debugObject.size.width / 2).toString(),
1446
- y: (debugObject.center.y - debugObject.size.height / 2).toString(),
1447
- width: debugObject.size.width.toString(),
1448
- height: debugObject.size.height.toString(),
1548
+ x: transformedX.toString(),
1549
+ y: Math.min(transformedY, transformedBottom).toString(),
1550
+ width: width.toString(),
1551
+ height: height.toString(),
1449
1552
  fill: "none",
1450
1553
  stroke: "red",
1451
- "stroke-width": "0.02",
1452
- "stroke-dasharray": "0.1,0.1"
1554
+ "stroke-width": (0.02 * Math.abs(transform.a)).toString(),
1555
+ "stroke-dasharray": "5,5"
1453
1556
  },
1454
1557
  children: debugObject.label ? [
1455
1558
  {
@@ -1457,10 +1560,10 @@ function createSvgObjectsFromSchDebugObject(debugObject) {
1457
1560
  type: "element",
1458
1561
  value: "",
1459
1562
  attributes: {
1460
- x: debugObject.center.x.toString(),
1461
- y: (debugObject.center.y - debugObject.size.height / 2 - 0.1).toString(),
1563
+ x: centerX.toString(),
1564
+ y: (centerY - 10).toString(),
1462
1565
  "text-anchor": "middle",
1463
- "font-size": "0.2",
1566
+ "font-size": (0.2 * Math.abs(transform.a)).toString(),
1464
1567
  fill: "red"
1465
1568
  },
1466
1569
  children: [
@@ -1478,19 +1581,31 @@ function createSvgObjectsFromSchDebugObject(debugObject) {
1478
1581
  ];
1479
1582
  }
1480
1583
  if (debugObject.shape === "line") {
1584
+ const [startX, startY] = applyToPoint15(transform, [
1585
+ debugObject.start.x,
1586
+ -debugObject.start.y
1587
+ // Flip Y
1588
+ ]);
1589
+ const [endX, endY] = applyToPoint15(transform, [
1590
+ debugObject.end.x,
1591
+ -debugObject.end.y
1592
+ // Flip Y
1593
+ ]);
1594
+ const midX = (startX + endX) / 2;
1595
+ const midY = (startY + endY) / 2;
1481
1596
  return [
1482
1597
  {
1483
1598
  name: "line",
1484
1599
  type: "element",
1485
1600
  value: "",
1486
1601
  attributes: {
1487
- x1: debugObject.start.x.toString(),
1488
- y1: debugObject.start.y.toString(),
1489
- x2: debugObject.end.x.toString(),
1490
- y2: debugObject.end.y.toString(),
1602
+ x1: startX.toString(),
1603
+ y1: startY.toString(),
1604
+ x2: endX.toString(),
1605
+ y2: endY.toString(),
1491
1606
  stroke: "red",
1492
- "stroke-width": "0.02",
1493
- "stroke-dasharray": "0.1,0.1"
1607
+ "stroke-width": (0.02 * Math.abs(transform.a)).toString(),
1608
+ "stroke-dasharray": "5,5"
1494
1609
  },
1495
1610
  children: debugObject.label ? [
1496
1611
  {
@@ -1498,10 +1613,10 @@ function createSvgObjectsFromSchDebugObject(debugObject) {
1498
1613
  type: "element",
1499
1614
  value: "",
1500
1615
  attributes: {
1501
- x: ((debugObject.start.x + debugObject.end.x) / 2).toString(),
1502
- y: ((debugObject.start.y + debugObject.end.y) / 2 - 0.1).toString(),
1616
+ x: midX.toString(),
1617
+ y: (midY - 10).toString(),
1503
1618
  "text-anchor": "middle",
1504
- "font-size": "0.2",
1619
+ "font-size": (0.2 * Math.abs(transform.a)).toString(),
1505
1620
  fill: "red"
1506
1621
  },
1507
1622
  children: [
@@ -1522,22 +1637,32 @@ function createSvgObjectsFromSchDebugObject(debugObject) {
1522
1637
  }
1523
1638
 
1524
1639
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts
1525
- function createSchematicTrace(trace, flipY, portPositions) {
1640
+ import { applyToPoint as applyToPoint16 } from "transformation-matrix";
1641
+ function createSchematicTrace(trace, transform) {
1526
1642
  const edges = trace.edges;
1527
1643
  if (edges.length === 0) return [];
1528
1644
  let path = "";
1529
1645
  edges.forEach((edge, index) => {
1530
- const fromPoint = edge.from.ti !== void 0 ? portPositions.get(edge.from.ti) : edge.from;
1531
- const toPoint = edge.to.ti !== void 0 ? portPositions.get(edge.to.ti) : edge.to;
1532
- if (!fromPoint || !toPoint) {
1533
- return;
1534
- }
1535
- const fromCoord = `${fromPoint.x - 0.15} ${flipY(fromPoint.y)}`;
1536
- const toCoord = `${toPoint.x + 0.15} ${flipY(toPoint.y)}`;
1646
+ const fromPoint = {
1647
+ x: (edge.from.x ?? edge.from.center?.x) - 0.15,
1648
+ y: edge.from.y ?? edge.from.center?.y
1649
+ };
1650
+ const toPoint = {
1651
+ x: (edge.to.x ?? edge.to.center?.x) + 0.15,
1652
+ y: edge.to.y ?? edge.to.center?.y
1653
+ };
1654
+ const [transformedFromX, transformedFromY] = applyToPoint16(transform, [
1655
+ fromPoint.x,
1656
+ fromPoint.y
1657
+ ]);
1658
+ const [transformedToX, transformedToY] = applyToPoint16(transform, [
1659
+ toPoint.x,
1660
+ toPoint.y
1661
+ ]);
1537
1662
  if (index === 0) {
1538
- path += `M ${fromCoord} L ${toCoord}`;
1663
+ path += `M ${transformedFromX} ${transformedFromY} L ${transformedToX} ${transformedToY}`;
1539
1664
  } else {
1540
- path += ` L ${toCoord}`;
1665
+ path += ` L ${transformedToX} ${transformedToY}`;
1541
1666
  }
1542
1667
  });
1543
1668
  return path ? [
@@ -1546,7 +1671,9 @@ function createSchematicTrace(trace, flipY, portPositions) {
1546
1671
  type: "element",
1547
1672
  attributes: {
1548
1673
  class: "trace",
1549
- d: path
1674
+ d: path,
1675
+ "stroke-width": (0.02 * Math.abs(transform.a)).toString()
1676
+ // Scale stroke width with transform
1550
1677
  },
1551
1678
  value: "",
1552
1679
  children: []
@@ -1555,23 +1682,41 @@ function createSchematicTrace(trace, flipY, portPositions) {
1555
1682
  }
1556
1683
 
1557
1684
  // lib/sch/convert-circuit-json-to-schematic-svg.ts
1558
- import { identity } from "transformation-matrix";
1559
1685
  function convertCircuitJsonToSchematicSvg(circuitJson, options) {
1560
- const portPositions = /* @__PURE__ */ new Map();
1561
- for (const item of circuitJson) {
1562
- if (item.type === "schematic_port") {
1563
- portPositions.set(item.schematic_port_id, item.center);
1564
- }
1565
- }
1566
1686
  const bounds = getSchematicBoundsFromCircuitJson(circuitJson);
1567
1687
  const { minX, minY, maxX, maxY } = bounds;
1568
- const viewBoxPadding = 0.5;
1569
- const width = maxX - minX + 2 * viewBoxPadding;
1570
- const height = maxY - minY;
1571
- const viewBox = `${minX - viewBoxPadding} ${minY - viewBoxPadding} ${width} ${height + 2 * viewBoxPadding}`;
1572
- const flipY = (y) => height - (y - minY) + minY;
1573
- const transform = identity();
1688
+ const padding = 1;
1689
+ const circuitWidth = maxX - minX + 2 * padding;
1690
+ const circuitHeight = maxY - minY + 2 * padding;
1691
+ const svgWidth = options?.width ?? 1200;
1692
+ const svgHeight = options?.height ?? 600;
1693
+ const scaleX = svgWidth / circuitWidth;
1694
+ const scaleY = svgHeight / circuitHeight;
1695
+ const scaleFactor = Math.min(scaleX, scaleY);
1696
+ const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
1697
+ const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
1698
+ const transform = compose4(
1699
+ translate4(
1700
+ offsetX - minX * scaleFactor + padding * scaleFactor,
1701
+ svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
1702
+ ),
1703
+ scale2(scaleFactor, -scaleFactor)
1704
+ // Flip in y-direction
1705
+ );
1574
1706
  const svgChildren = [];
1707
+ svgChildren.push({
1708
+ name: "rect",
1709
+ type: "element",
1710
+ attributes: {
1711
+ class: "boundary",
1712
+ x: "0",
1713
+ y: "0",
1714
+ width: svgWidth.toString(),
1715
+ height: svgHeight.toString()
1716
+ },
1717
+ children: [],
1718
+ value: ""
1719
+ });
1575
1720
  if (options?.grid) {
1576
1721
  const gridConfig = typeof options.grid === "object" ? options.grid : {};
1577
1722
  svgChildren.push(drawSchematicGrid({ bounds, transform, ...gridConfig }));
@@ -1589,21 +1734,19 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
1589
1734
  const schTraceSvgs = [];
1590
1735
  for (const elm of circuitJson) {
1591
1736
  if (elm.type === "schematic_debug_object") {
1592
- schDebugObjectSvgs.push(...createSvgObjectsFromSchDebugObject(elm));
1737
+ schDebugObjectSvgs.push(
1738
+ ...createSvgObjectsFromSchDebugObject(elm, transform)
1739
+ );
1593
1740
  } else if (elm.type === "schematic_component") {
1594
1741
  schComponentSvgs.push(
1595
1742
  ...createSchematicComponent({
1596
- component: {
1597
- ...elm,
1598
- center: { x: elm.center.x, y: flipY(elm.center.y) }
1599
- },
1743
+ component: elm,
1600
1744
  transform,
1601
- // Add the missing transform property
1602
1745
  circuitJson
1603
1746
  })
1604
1747
  );
1605
1748
  } else if (elm.type === "schematic_trace") {
1606
- schTraceSvgs.push(...createSchematicTrace(elm, flipY, portPositions));
1749
+ schTraceSvgs.push(...createSchematicTrace(elm, transform));
1607
1750
  }
1608
1751
  }
1609
1752
  svgChildren.push(...schDebugObjectSvgs, ...schComponentSvgs, ...schTraceSvgs);
@@ -1612,12 +1755,12 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
1612
1755
  type: "element",
1613
1756
  attributes: {
1614
1757
  xmlns: "http://www.w3.org/2000/svg",
1615
- viewBox,
1616
- width: (options?.width ?? 1200).toString(),
1617
- height: (options?.height ?? 600).toString(),
1758
+ width: svgWidth.toString(),
1759
+ height: svgHeight.toString(),
1618
1760
  style: `background-color: ${colorMap.schematic.background}`
1619
1761
  },
1620
1762
  children: [
1763
+ // Add styles
1621
1764
  {
1622
1765
  name: "style",
1623
1766
  type: "element",
@@ -1625,14 +1768,16 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
1625
1768
  {
1626
1769
  type: "text",
1627
1770
  value: `
1628
- .component { fill: none; stroke: ${colorMap.schematic.component_outline}; stroke-width: 0.03; }
1629
- .chip { fill: ${colorMap.schematic.component_body}; stroke: ${colorMap.schematic.component_outline}; stroke-width: 0.03; }
1630
- .component-pin { fill: none; stroke: ${colorMap.schematic.component_outline}; stroke-width: 0.02; }
1631
- .trace { stroke: ${colorMap.schematic.wire}; stroke-width: 0.02; fill: none; }
1632
- .text { font-family: Arial, sans-serif; font-size: 0.2px; fill: ${colorMap.schematic.wire}; }
1633
- .pin-number { font-size: 0.15px; fill: ${colorMap.schematic.pin_number}; }
1771
+ .boundary { fill: ${colorMap.schematic.background}; }
1772
+ .schematic-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }
1773
+ .component { fill: none; stroke: ${colorMap.schematic.component_outline}; }
1774
+ .chip { fill: ${colorMap.schematic.component_body}; stroke: ${colorMap.schematic.component_outline}; }
1775
+ .component-pin { fill: none; stroke: ${colorMap.schematic.component_outline}; }
1776
+ .trace { stroke: ${colorMap.schematic.wire}; stroke-width: ${0.02 * scaleFactor}; fill: none; }
1777
+ .text { font-family: Arial, sans-serif; font-size: ${0.2 * scaleFactor}px; fill: ${colorMap.schematic.wire}; }
1778
+ .pin-number { font-size: ${0.15 * scaleFactor}px; fill: ${colorMap.schematic.pin_number}; }
1634
1779
  .port-label { fill: ${colorMap.schematic.reference}; }
1635
- .component-name { font-size: 0.25px; fill: ${colorMap.schematic.reference}; }
1780
+ .component-name { font-size: ${0.25 * scaleFactor}px; fill: ${colorMap.schematic.reference}; }
1636
1781
  `,
1637
1782
  name: "",
1638
1783
  attributes: {},
@@ -1646,14 +1791,7 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
1646
1791
  ],
1647
1792
  value: ""
1648
1793
  };
1649
- return stringify2({
1650
- ...svgObject,
1651
- attributes: {
1652
- ...svgObject.attributes,
1653
- width: svgObject.attributes.width?.toString(),
1654
- height: svgObject.attributes.height?.toString()
1655
- }
1656
- });
1794
+ return stringify2(svgObject);
1657
1795
  }
1658
1796
  var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
1659
1797
  export {