circuit-to-svg 0.0.47 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -2
- package/dist/index.js +429 -292
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -976,14 +976,184 @@ 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
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// lib/sch/draw-schematic-grid.ts
|
|
1024
|
+
function drawSchematicGrid(params) {
|
|
1025
|
+
const { minX, minY, maxX, maxY } = params.bounds;
|
|
1026
|
+
const cellSize = params.cellSize ?? 1;
|
|
1027
|
+
const labelCells = params.labelCells ?? false;
|
|
1028
|
+
const gridLines = [];
|
|
1029
|
+
for (let x = Math.ceil(minX); x <= Math.floor(maxX); x += cellSize) {
|
|
1030
|
+
gridLines.push({
|
|
1031
|
+
name: "line",
|
|
1032
|
+
type: "element",
|
|
1033
|
+
attributes: {
|
|
1034
|
+
x1: x.toString(),
|
|
1035
|
+
y1: minY.toString(),
|
|
1036
|
+
x2: x.toString(),
|
|
1037
|
+
y2: maxY.toString(),
|
|
1038
|
+
stroke: colorMap.schematic.grid,
|
|
1039
|
+
"stroke-width": "0.01",
|
|
1040
|
+
"stroke-opacity": "0.5"
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
for (let y = Math.ceil(minY); y <= Math.floor(maxY); y += cellSize) {
|
|
1045
|
+
gridLines.push({
|
|
1046
|
+
name: "line",
|
|
1047
|
+
type: "element",
|
|
1048
|
+
attributes: {
|
|
1049
|
+
x1: minX.toString(),
|
|
1050
|
+
y1: y.toString(),
|
|
1051
|
+
x2: maxX.toString(),
|
|
1052
|
+
y2: y.toString(),
|
|
1053
|
+
stroke: colorMap.schematic.grid,
|
|
1054
|
+
"stroke-width": "0.01",
|
|
1055
|
+
"stroke-opacity": "0.5"
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
if (labelCells) {
|
|
1060
|
+
for (let x = Math.ceil(minX); x <= Math.floor(maxX); x += cellSize) {
|
|
1061
|
+
for (let y = Math.ceil(minY); y <= Math.floor(maxY); y += cellSize) {
|
|
1062
|
+
gridLines.push({
|
|
1063
|
+
name: "text",
|
|
1064
|
+
type: "element",
|
|
1065
|
+
attributes: {
|
|
1066
|
+
x: x.toString(),
|
|
1067
|
+
y: y.toString(),
|
|
1068
|
+
fill: colorMap.schematic.grid,
|
|
1069
|
+
"font-size": (cellSize / 6).toString(),
|
|
1070
|
+
"fill-opacity": "0.5"
|
|
1071
|
+
},
|
|
1072
|
+
children: [
|
|
1073
|
+
{
|
|
1074
|
+
type: "text",
|
|
1075
|
+
value: `${x},${y}`,
|
|
1076
|
+
name: "",
|
|
1077
|
+
attributes: {},
|
|
1078
|
+
children: []
|
|
1079
|
+
}
|
|
1080
|
+
]
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
return {
|
|
1086
|
+
name: "g",
|
|
1087
|
+
value: "",
|
|
1088
|
+
type: "element",
|
|
1089
|
+
attributes: { class: "grid" },
|
|
1090
|
+
children: gridLines
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// lib/sch/draw-schematic-labeled-points.ts
|
|
1095
|
+
function drawSchematicLabeledPoints(params) {
|
|
1096
|
+
const { points, transform } = params;
|
|
1097
|
+
const labeledPointsGroup = [];
|
|
1098
|
+
for (const point of points) {
|
|
1099
|
+
labeledPointsGroup.push({
|
|
1100
|
+
name: "path",
|
|
1101
|
+
type: "element",
|
|
1102
|
+
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}`,
|
|
1104
|
+
stroke: colorMap.schematic.grid,
|
|
1105
|
+
"stroke-width": "0.02",
|
|
1106
|
+
"stroke-opacity": "0.7"
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1109
|
+
labeledPointsGroup.push({
|
|
1110
|
+
name: "text",
|
|
1111
|
+
type: "element",
|
|
1112
|
+
attributes: {
|
|
1113
|
+
x: (point.x + 0.15).toString(),
|
|
1114
|
+
y: (point.y - 0.15).toString(),
|
|
1115
|
+
fill: colorMap.schematic.grid,
|
|
1116
|
+
"font-size": "0.15",
|
|
1117
|
+
"fill-opacity": "0.7"
|
|
1118
|
+
},
|
|
1119
|
+
children: [
|
|
1120
|
+
{
|
|
1121
|
+
type: "text",
|
|
1122
|
+
value: point.label || `(${point.x},${point.y})`,
|
|
1123
|
+
name: "",
|
|
1124
|
+
attributes: {},
|
|
1125
|
+
children: []
|
|
1126
|
+
}
|
|
1127
|
+
]
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
return {
|
|
1131
|
+
name: "g",
|
|
1132
|
+
value: "",
|
|
1133
|
+
type: "element",
|
|
1134
|
+
attributes: { class: "labeled-points" },
|
|
1135
|
+
children: labeledPointsGroup
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
|
|
979
1139
|
// lib/sch/convert-circuit-json-to-schematic-svg.ts
|
|
980
1140
|
import { stringify as stringify2 } from "svgson";
|
|
981
1141
|
|
|
982
1142
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component.ts
|
|
983
1143
|
import { getSvg, symbols } from "schematic-symbols";
|
|
984
1144
|
import { parseSync } from "svgson";
|
|
985
|
-
function createSchematicComponent(
|
|
986
|
-
|
|
1145
|
+
function createSchematicComponent({
|
|
1146
|
+
component,
|
|
1147
|
+
circuitJson
|
|
1148
|
+
}) {
|
|
1149
|
+
const center = component.center;
|
|
1150
|
+
const size = component.size;
|
|
1151
|
+
const rotation = component.rotation;
|
|
1152
|
+
const symbolName = component.symbol_name;
|
|
1153
|
+
const portLabels = component.port_labels;
|
|
1154
|
+
const sourceComponentId = component.source_component_id;
|
|
1155
|
+
const schematicComponentId = component.schematic_component_id;
|
|
1156
|
+
const transformString = `translate(${center.x}, ${center.y}) rotate(${rotation * 180 / Math.PI})`;
|
|
987
1157
|
let children = [];
|
|
988
1158
|
const sourceComponent = circuitJson?.find(
|
|
989
1159
|
(item) => item.type === "source_component" && item.source_component_id === sourceComponentId
|
|
@@ -1025,13 +1195,15 @@ function createSchematicComponent(center, size, rotation, symbolName, portLabels
|
|
|
1025
1195
|
children.push({
|
|
1026
1196
|
name: "rect",
|
|
1027
1197
|
type: "element",
|
|
1198
|
+
value: "",
|
|
1028
1199
|
attributes: {
|
|
1029
1200
|
class: "component chip",
|
|
1030
|
-
x: -size.width / 2,
|
|
1031
|
-
y: -size.height / 2,
|
|
1032
|
-
width: size.width,
|
|
1033
|
-
height: size.height
|
|
1034
|
-
}
|
|
1201
|
+
x: (-size.width / 2).toString(),
|
|
1202
|
+
y: (-size.height / 2).toString(),
|
|
1203
|
+
width: size.width.toString(),
|
|
1204
|
+
height: size.height.toString()
|
|
1205
|
+
},
|
|
1206
|
+
children: []
|
|
1035
1207
|
});
|
|
1036
1208
|
if (manufacturerNumber) {
|
|
1037
1209
|
children.push({
|
|
@@ -1039,24 +1211,42 @@ function createSchematicComponent(center, size, rotation, symbolName, portLabels
|
|
|
1039
1211
|
type: "element",
|
|
1040
1212
|
attributes: {
|
|
1041
1213
|
class: "component-name",
|
|
1042
|
-
x: 1.2,
|
|
1043
|
-
y: -size.height / 2 - 0.5,
|
|
1214
|
+
x: 1.2.toString(),
|
|
1215
|
+
y: (-size.height / 2 - 0.5).toString(),
|
|
1044
1216
|
"text-anchor": "right",
|
|
1045
1217
|
"dominant-baseline": "auto"
|
|
1046
1218
|
},
|
|
1047
|
-
children: [
|
|
1219
|
+
children: [
|
|
1220
|
+
{
|
|
1221
|
+
type: "text",
|
|
1222
|
+
value: manufacturerNumber,
|
|
1223
|
+
name: "",
|
|
1224
|
+
attributes: {},
|
|
1225
|
+
children: []
|
|
1226
|
+
}
|
|
1227
|
+
],
|
|
1228
|
+
value: ""
|
|
1048
1229
|
});
|
|
1049
1230
|
children.push({
|
|
1050
1231
|
name: "text",
|
|
1051
1232
|
type: "element",
|
|
1052
1233
|
attributes: {
|
|
1053
1234
|
class: "component-name",
|
|
1054
|
-
x: 1.2,
|
|
1055
|
-
y: -size.height / 2 - 0.7,
|
|
1235
|
+
x: 1.2.toString(),
|
|
1236
|
+
y: (-size.height / 2 - 0.7).toString(),
|
|
1056
1237
|
"text-anchor": "right",
|
|
1057
1238
|
"dominant-baseline": "auto"
|
|
1058
1239
|
},
|
|
1059
|
-
children: [
|
|
1240
|
+
children: [
|
|
1241
|
+
{
|
|
1242
|
+
type: "text",
|
|
1243
|
+
value: componentName || "",
|
|
1244
|
+
name: "",
|
|
1245
|
+
attributes: {},
|
|
1246
|
+
children: []
|
|
1247
|
+
}
|
|
1248
|
+
],
|
|
1249
|
+
value: ""
|
|
1060
1250
|
});
|
|
1061
1251
|
}
|
|
1062
1252
|
const schematicPorts = circuitJson?.filter(
|
|
@@ -1101,21 +1291,25 @@ function createSchematicComponent(center, size, rotation, symbolName, portLabels
|
|
|
1101
1291
|
type: "element",
|
|
1102
1292
|
attributes: {
|
|
1103
1293
|
class: "component-pin",
|
|
1104
|
-
x1: x,
|
|
1105
|
-
y1: y,
|
|
1106
|
-
x2: endX,
|
|
1107
|
-
y2: endY
|
|
1108
|
-
}
|
|
1294
|
+
x1: x.toString(),
|
|
1295
|
+
y1: y.toString(),
|
|
1296
|
+
x2: endX.toString(),
|
|
1297
|
+
y2: endY.toString()
|
|
1298
|
+
},
|
|
1299
|
+
value: "",
|
|
1300
|
+
children: []
|
|
1109
1301
|
});
|
|
1110
1302
|
children.push({
|
|
1111
1303
|
name: "circle",
|
|
1112
1304
|
type: "element",
|
|
1113
1305
|
attributes: {
|
|
1114
1306
|
class: "component-pin",
|
|
1115
|
-
cx: endX,
|
|
1116
|
-
cy: endY,
|
|
1117
|
-
r: circleRadius
|
|
1118
|
-
}
|
|
1307
|
+
cx: endX.toString(),
|
|
1308
|
+
cy: endY.toString(),
|
|
1309
|
+
r: circleRadius.toString()
|
|
1310
|
+
},
|
|
1311
|
+
value: "",
|
|
1312
|
+
children: []
|
|
1119
1313
|
});
|
|
1120
1314
|
const labelKey = `pin${pinNumber}`;
|
|
1121
1315
|
if (portLabels && labelKey in portLabels) {
|
|
@@ -1124,13 +1318,22 @@ function createSchematicComponent(center, size, rotation, symbolName, portLabels
|
|
|
1124
1318
|
type: "element",
|
|
1125
1319
|
attributes: {
|
|
1126
1320
|
class: "port-label",
|
|
1127
|
-
x: labelX,
|
|
1128
|
-
y: labelY,
|
|
1321
|
+
x: labelX.toString(),
|
|
1322
|
+
y: labelY.toString(),
|
|
1129
1323
|
"text-anchor": textAnchor,
|
|
1130
1324
|
"dominant-baseline": dominantBaseline,
|
|
1131
1325
|
"font-size": "0.2"
|
|
1132
1326
|
},
|
|
1133
|
-
children: [
|
|
1327
|
+
children: [
|
|
1328
|
+
{
|
|
1329
|
+
type: "text",
|
|
1330
|
+
value: portLabels[labelKey],
|
|
1331
|
+
name: "",
|
|
1332
|
+
attributes: {},
|
|
1333
|
+
children: []
|
|
1334
|
+
}
|
|
1335
|
+
],
|
|
1336
|
+
value: ""
|
|
1134
1337
|
});
|
|
1135
1338
|
}
|
|
1136
1339
|
const pinNumberX = endX;
|
|
@@ -1156,13 +1359,22 @@ function createSchematicComponent(center, size, rotation, symbolName, portLabels
|
|
|
1156
1359
|
type: "element",
|
|
1157
1360
|
attributes: {
|
|
1158
1361
|
class: "pin-number",
|
|
1159
|
-
x: pinNumberX,
|
|
1160
|
-
y: pinNumberY,
|
|
1362
|
+
x: pinNumberX.toString(),
|
|
1363
|
+
y: pinNumberY.toString(),
|
|
1161
1364
|
"text-anchor": pinNumberAnchor,
|
|
1162
1365
|
"dominant-baseline": pinNumberBaseline,
|
|
1163
1366
|
"font-size": "0.15"
|
|
1164
1367
|
},
|
|
1165
|
-
|
|
1368
|
+
value: "",
|
|
1369
|
+
children: [
|
|
1370
|
+
{
|
|
1371
|
+
type: "text",
|
|
1372
|
+
value: pinNumber.toString(),
|
|
1373
|
+
name: "",
|
|
1374
|
+
attributes: {},
|
|
1375
|
+
children: []
|
|
1376
|
+
}
|
|
1377
|
+
]
|
|
1166
1378
|
});
|
|
1167
1379
|
}
|
|
1168
1380
|
}
|
|
@@ -1172,262 +1384,237 @@ function createSchematicComponent(center, size, rotation, symbolName, portLabels
|
|
|
1172
1384
|
type: "element",
|
|
1173
1385
|
attributes: {
|
|
1174
1386
|
class: "component-name",
|
|
1175
|
-
x: 0,
|
|
1176
|
-
y: -size.height / 2 - 0.2,
|
|
1387
|
+
x: "0",
|
|
1388
|
+
y: (-size.height / 2 - 0.2).toString(),
|
|
1177
1389
|
"text-anchor": "middle",
|
|
1178
1390
|
"dominant-baseline": "auto"
|
|
1179
1391
|
},
|
|
1180
|
-
|
|
1392
|
+
value: "",
|
|
1393
|
+
children: [
|
|
1394
|
+
{
|
|
1395
|
+
type: "text",
|
|
1396
|
+
value: (resistance || capacitance || "").toString(),
|
|
1397
|
+
name: "",
|
|
1398
|
+
attributes: {},
|
|
1399
|
+
children: []
|
|
1400
|
+
}
|
|
1401
|
+
]
|
|
1181
1402
|
});
|
|
1182
1403
|
children.push({
|
|
1183
1404
|
name: "text",
|
|
1184
1405
|
type: "element",
|
|
1185
1406
|
attributes: {
|
|
1186
1407
|
class: "component-name",
|
|
1187
|
-
x: 0,
|
|
1188
|
-
y: -size.height / 2 - 0.5,
|
|
1408
|
+
x: "0",
|
|
1409
|
+
y: (-size.height / 2 - 0.5).toString(),
|
|
1189
1410
|
"text-anchor": "middle",
|
|
1190
1411
|
"dominant-baseline": "auto"
|
|
1191
1412
|
},
|
|
1192
|
-
|
|
1413
|
+
value: "",
|
|
1414
|
+
children: [
|
|
1415
|
+
{
|
|
1416
|
+
type: "text",
|
|
1417
|
+
value: componentName || "",
|
|
1418
|
+
name: "",
|
|
1419
|
+
attributes: {},
|
|
1420
|
+
children: []
|
|
1421
|
+
}
|
|
1422
|
+
]
|
|
1193
1423
|
});
|
|
1194
1424
|
}
|
|
1195
|
-
return
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1425
|
+
return [
|
|
1426
|
+
{
|
|
1427
|
+
name: "g",
|
|
1428
|
+
value: "",
|
|
1429
|
+
type: "element",
|
|
1430
|
+
attributes: { transform: transformString },
|
|
1431
|
+
children
|
|
1432
|
+
}
|
|
1433
|
+
];
|
|
1201
1434
|
}
|
|
1202
1435
|
|
|
1203
1436
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-debug-object.ts
|
|
1204
1437
|
function createSvgObjectsFromSchDebugObject(debugObject) {
|
|
1205
1438
|
if (debugObject.shape === "rect") {
|
|
1206
|
-
return [
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
value: "",
|
|
1210
|
-
attributes: {
|
|
1211
|
-
x: (debugObject.center.x - debugObject.size.width / 2).toString(),
|
|
1212
|
-
y: (debugObject.center.y - debugObject.size.height / 2).toString(),
|
|
1213
|
-
width: debugObject.size.width.toString(),
|
|
1214
|
-
height: debugObject.size.height.toString(),
|
|
1215
|
-
fill: "none",
|
|
1216
|
-
stroke: "red",
|
|
1217
|
-
"stroke-width": "0.02",
|
|
1218
|
-
"stroke-dasharray": "0.1,0.1"
|
|
1219
|
-
},
|
|
1220
|
-
children: debugObject.label ? [{
|
|
1221
|
-
name: "text",
|
|
1439
|
+
return [
|
|
1440
|
+
{
|
|
1441
|
+
name: "rect",
|
|
1222
1442
|
type: "element",
|
|
1223
1443
|
value: "",
|
|
1224
1444
|
attributes: {
|
|
1225
|
-
x: debugObject.center.x.toString(),
|
|
1226
|
-
y: (debugObject.center.y - debugObject.size.height / 2
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
fill: "
|
|
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(),
|
|
1449
|
+
fill: "none",
|
|
1450
|
+
stroke: "red",
|
|
1451
|
+
"stroke-width": "0.02",
|
|
1452
|
+
"stroke-dasharray": "0.1,0.1"
|
|
1230
1453
|
},
|
|
1231
|
-
children: [
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1454
|
+
children: debugObject.label ? [
|
|
1455
|
+
{
|
|
1456
|
+
name: "text",
|
|
1457
|
+
type: "element",
|
|
1458
|
+
value: "",
|
|
1459
|
+
attributes: {
|
|
1460
|
+
x: debugObject.center.x.toString(),
|
|
1461
|
+
y: (debugObject.center.y - debugObject.size.height / 2 - 0.1).toString(),
|
|
1462
|
+
"text-anchor": "middle",
|
|
1463
|
+
"font-size": "0.2",
|
|
1464
|
+
fill: "red"
|
|
1465
|
+
},
|
|
1466
|
+
children: [
|
|
1467
|
+
{
|
|
1468
|
+
type: "text",
|
|
1469
|
+
value: debugObject.label,
|
|
1470
|
+
name: "",
|
|
1471
|
+
attributes: {},
|
|
1472
|
+
children: []
|
|
1473
|
+
}
|
|
1474
|
+
]
|
|
1475
|
+
}
|
|
1476
|
+
] : []
|
|
1477
|
+
}
|
|
1478
|
+
];
|
|
1240
1479
|
}
|
|
1241
1480
|
if (debugObject.shape === "line") {
|
|
1242
|
-
return [
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
value: "",
|
|
1246
|
-
attributes: {
|
|
1247
|
-
x1: debugObject.start.x.toString(),
|
|
1248
|
-
y1: debugObject.start.y.toString(),
|
|
1249
|
-
x2: debugObject.end.x.toString(),
|
|
1250
|
-
y2: debugObject.end.y.toString(),
|
|
1251
|
-
stroke: "red",
|
|
1252
|
-
"stroke-width": "0.02",
|
|
1253
|
-
"stroke-dasharray": "0.1,0.1"
|
|
1254
|
-
},
|
|
1255
|
-
children: debugObject.label ? [{
|
|
1256
|
-
name: "text",
|
|
1481
|
+
return [
|
|
1482
|
+
{
|
|
1483
|
+
name: "line",
|
|
1257
1484
|
type: "element",
|
|
1258
1485
|
value: "",
|
|
1259
1486
|
attributes: {
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1487
|
+
x1: debugObject.start.x.toString(),
|
|
1488
|
+
y1: debugObject.start.y.toString(),
|
|
1489
|
+
x2: debugObject.end.x.toString(),
|
|
1490
|
+
y2: debugObject.end.y.toString(),
|
|
1491
|
+
stroke: "red",
|
|
1492
|
+
"stroke-width": "0.02",
|
|
1493
|
+
"stroke-dasharray": "0.1,0.1"
|
|
1265
1494
|
},
|
|
1266
|
-
children: [
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1495
|
+
children: debugObject.label ? [
|
|
1496
|
+
{
|
|
1497
|
+
name: "text",
|
|
1498
|
+
type: "element",
|
|
1499
|
+
value: "",
|
|
1500
|
+
attributes: {
|
|
1501
|
+
x: ((debugObject.start.x + debugObject.end.x) / 2).toString(),
|
|
1502
|
+
y: ((debugObject.start.y + debugObject.end.y) / 2 - 0.1).toString(),
|
|
1503
|
+
"text-anchor": "middle",
|
|
1504
|
+
"font-size": "0.2",
|
|
1505
|
+
fill: "red"
|
|
1506
|
+
},
|
|
1507
|
+
children: [
|
|
1508
|
+
{
|
|
1509
|
+
type: "text",
|
|
1510
|
+
value: debugObject.label,
|
|
1511
|
+
name: "",
|
|
1512
|
+
attributes: {},
|
|
1513
|
+
children: []
|
|
1514
|
+
}
|
|
1515
|
+
]
|
|
1516
|
+
}
|
|
1517
|
+
] : []
|
|
1518
|
+
}
|
|
1519
|
+
];
|
|
1275
1520
|
}
|
|
1276
1521
|
return [];
|
|
1277
1522
|
}
|
|
1278
1523
|
|
|
1524
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts
|
|
1525
|
+
function createSchematicTrace(trace, flipY, portPositions) {
|
|
1526
|
+
const edges = trace.edges;
|
|
1527
|
+
if (edges.length === 0) return [];
|
|
1528
|
+
let path = "";
|
|
1529
|
+
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)}`;
|
|
1537
|
+
if (index === 0) {
|
|
1538
|
+
path += `M ${fromCoord} L ${toCoord}`;
|
|
1539
|
+
} else {
|
|
1540
|
+
path += ` L ${toCoord}`;
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
return path ? [
|
|
1544
|
+
{
|
|
1545
|
+
name: "path",
|
|
1546
|
+
type: "element",
|
|
1547
|
+
attributes: {
|
|
1548
|
+
class: "trace",
|
|
1549
|
+
d: path
|
|
1550
|
+
},
|
|
1551
|
+
value: "",
|
|
1552
|
+
children: []
|
|
1553
|
+
}
|
|
1554
|
+
] : [];
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1279
1557
|
// lib/sch/convert-circuit-json-to-schematic-svg.ts
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
let minY = Number.POSITIVE_INFINITY;
|
|
1283
|
-
let maxX = Number.NEGATIVE_INFINITY;
|
|
1284
|
-
let maxY = Number.NEGATIVE_INFINITY;
|
|
1285
|
-
const portSize = 0.2;
|
|
1558
|
+
import { identity } from "transformation-matrix";
|
|
1559
|
+
function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
1286
1560
|
const portPositions = /* @__PURE__ */ new Map();
|
|
1287
|
-
for (const item of
|
|
1288
|
-
if (item.type === "
|
|
1289
|
-
updateBounds(item.center, item.size, item.rotation || 0);
|
|
1290
|
-
} else if (item.type === "schematic_port") {
|
|
1291
|
-
updateBounds(item.center, { width: portSize, height: portSize }, 0);
|
|
1561
|
+
for (const item of circuitJson) {
|
|
1562
|
+
if (item.type === "schematic_port") {
|
|
1292
1563
|
portPositions.set(item.schematic_port_id, item.center);
|
|
1293
|
-
} else if (item.type === "schematic_debug_object") {
|
|
1294
|
-
if (item.shape === "rect") {
|
|
1295
|
-
updateBounds(item.center, item.size, 0);
|
|
1296
|
-
} else if (item.shape === "line") {
|
|
1297
|
-
updateBounds(item.start, { width: 0.1, height: 0.1 }, 0);
|
|
1298
|
-
updateBounds(item.end, { width: 0.1, height: 0.1 }, 0);
|
|
1299
|
-
}
|
|
1300
1564
|
}
|
|
1301
1565
|
}
|
|
1302
|
-
const
|
|
1303
|
-
minX
|
|
1304
|
-
|
|
1305
|
-
maxX
|
|
1306
|
-
maxY += padding;
|
|
1566
|
+
const bounds = getSchematicBoundsFromCircuitJson(circuitJson);
|
|
1567
|
+
const { minX, minY, maxX, maxY } = bounds;
|
|
1568
|
+
const viewBoxPadding = 0.5;
|
|
1569
|
+
const width = maxX - minX + 2 * viewBoxPadding;
|
|
1307
1570
|
const height = maxY - minY;
|
|
1571
|
+
const viewBox = `${minX - viewBoxPadding} ${minY - viewBoxPadding} ${width} ${height + 2 * viewBoxPadding}`;
|
|
1308
1572
|
const flipY = (y) => height - (y - minY) + minY;
|
|
1573
|
+
const transform = identity();
|
|
1309
1574
|
const svgChildren = [];
|
|
1310
1575
|
if (options?.grid) {
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
for (let x = Math.ceil(minX); x <= Math.floor(maxX); x += cellSize) {
|
|
1314
|
-
gridLines.push({
|
|
1315
|
-
name: "line",
|
|
1316
|
-
type: "element",
|
|
1317
|
-
attributes: {
|
|
1318
|
-
x1: x.toString(),
|
|
1319
|
-
y1: minY.toString(),
|
|
1320
|
-
x2: x.toString(),
|
|
1321
|
-
y2: maxY.toString(),
|
|
1322
|
-
stroke: colorMap.schematic.grid,
|
|
1323
|
-
"stroke-width": "0.01",
|
|
1324
|
-
"stroke-opacity": "0.5"
|
|
1325
|
-
}
|
|
1326
|
-
});
|
|
1327
|
-
}
|
|
1328
|
-
for (let y = Math.ceil(minY); y <= Math.floor(maxY); y += cellSize) {
|
|
1329
|
-
gridLines.push({
|
|
1330
|
-
name: "line",
|
|
1331
|
-
type: "element",
|
|
1332
|
-
attributes: {
|
|
1333
|
-
x1: minX.toString(),
|
|
1334
|
-
y1: y.toString(),
|
|
1335
|
-
x2: maxX.toString(),
|
|
1336
|
-
y2: y.toString(),
|
|
1337
|
-
stroke: colorMap.schematic.grid,
|
|
1338
|
-
"stroke-width": "0.01",
|
|
1339
|
-
"stroke-opacity": "0.5"
|
|
1340
|
-
}
|
|
1341
|
-
});
|
|
1342
|
-
}
|
|
1343
|
-
svgChildren.push({
|
|
1344
|
-
name: "g",
|
|
1345
|
-
type: "element",
|
|
1346
|
-
attributes: { class: "grid" },
|
|
1347
|
-
children: gridLines
|
|
1348
|
-
});
|
|
1576
|
+
const gridConfig = typeof options.grid === "object" ? options.grid : {};
|
|
1577
|
+
svgChildren.push(drawSchematicGrid({ bounds, transform, ...gridConfig }));
|
|
1349
1578
|
}
|
|
1350
1579
|
if (options?.labeledPoints) {
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
attributes: {
|
|
1357
|
-
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}`,
|
|
1358
|
-
stroke: colorMap.schematic.grid,
|
|
1359
|
-
"stroke-width": "0.02",
|
|
1360
|
-
"stroke-opacity": "0.7"
|
|
1361
|
-
}
|
|
1362
|
-
});
|
|
1363
|
-
labeledPointsGroup.push({
|
|
1364
|
-
name: "text",
|
|
1365
|
-
type: "element",
|
|
1366
|
-
attributes: {
|
|
1367
|
-
x: (point.x + 0.15).toString(),
|
|
1368
|
-
y: (point.y - 0.15).toString(),
|
|
1369
|
-
fill: colorMap.schematic.grid,
|
|
1370
|
-
"font-size": "0.15",
|
|
1371
|
-
"fill-opacity": "0.7"
|
|
1372
|
-
},
|
|
1373
|
-
children: [{
|
|
1374
|
-
type: "text",
|
|
1375
|
-
value: point.label || `(${point.x},${point.y})`,
|
|
1376
|
-
name: "",
|
|
1377
|
-
attributes: {},
|
|
1378
|
-
children: []
|
|
1379
|
-
}]
|
|
1380
|
-
});
|
|
1381
|
-
}
|
|
1382
|
-
svgChildren.push({
|
|
1383
|
-
name: "g",
|
|
1384
|
-
type: "element",
|
|
1385
|
-
attributes: { class: "labeled-points" },
|
|
1386
|
-
children: labeledPointsGroup
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1389
|
-
for (const debugObj of soup.filter(
|
|
1390
|
-
(item) => item.type === "schematic_debug_object"
|
|
1391
|
-
)) {
|
|
1392
|
-
const svg = createSvgObjectsFromSchDebugObject(debugObj);
|
|
1393
|
-
svgChildren.push(...svg);
|
|
1394
|
-
}
|
|
1395
|
-
const componentMap = /* @__PURE__ */ new Map();
|
|
1396
|
-
for (const component of soup.filter(
|
|
1397
|
-
(item) => item.type === "schematic_component"
|
|
1398
|
-
)) {
|
|
1399
|
-
const flippedCenter = {
|
|
1400
|
-
x: component.center.x,
|
|
1401
|
-
y: flipY(component.center.y)
|
|
1402
|
-
};
|
|
1403
|
-
const svg = createSchematicComponent(
|
|
1404
|
-
flippedCenter,
|
|
1405
|
-
component.size,
|
|
1406
|
-
component.rotation || 0,
|
|
1407
|
-
component.symbol_name,
|
|
1408
|
-
component.port_labels,
|
|
1409
|
-
component.source_component_id,
|
|
1410
|
-
component.schematic_component_id,
|
|
1411
|
-
soup
|
|
1580
|
+
svgChildren.push(
|
|
1581
|
+
drawSchematicLabeledPoints({
|
|
1582
|
+
points: options.labeledPoints,
|
|
1583
|
+
transform
|
|
1584
|
+
})
|
|
1412
1585
|
);
|
|
1413
|
-
svgChildren.push(svg);
|
|
1414
|
-
componentMap.set(component.schematic_component_id, component);
|
|
1415
1586
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1587
|
+
const schDebugObjectSvgs = [];
|
|
1588
|
+
const schComponentSvgs = [];
|
|
1589
|
+
const schTraceSvgs = [];
|
|
1590
|
+
for (const elm of circuitJson) {
|
|
1591
|
+
if (elm.type === "schematic_debug_object") {
|
|
1592
|
+
schDebugObjectSvgs.push(...createSvgObjectsFromSchDebugObject(elm));
|
|
1593
|
+
} else if (elm.type === "schematic_component") {
|
|
1594
|
+
schComponentSvgs.push(
|
|
1595
|
+
...createSchematicComponent({
|
|
1596
|
+
component: {
|
|
1597
|
+
...elm,
|
|
1598
|
+
center: { x: elm.center.x, y: flipY(elm.center.y) }
|
|
1599
|
+
},
|
|
1600
|
+
transform,
|
|
1601
|
+
// Add the missing transform property
|
|
1602
|
+
circuitJson
|
|
1603
|
+
})
|
|
1604
|
+
);
|
|
1605
|
+
} else if (elm.type === "schematic_trace") {
|
|
1606
|
+
schTraceSvgs.push(...createSchematicTrace(elm, flipY, portPositions));
|
|
1607
|
+
}
|
|
1419
1608
|
}
|
|
1420
|
-
|
|
1421
|
-
const width = maxX - minX + 2 * padding;
|
|
1422
|
-
const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`;
|
|
1609
|
+
svgChildren.push(...schDebugObjectSvgs, ...schComponentSvgs, ...schTraceSvgs);
|
|
1423
1610
|
const svgObject = {
|
|
1424
1611
|
name: "svg",
|
|
1425
1612
|
type: "element",
|
|
1426
1613
|
attributes: {
|
|
1427
1614
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1428
1615
|
viewBox,
|
|
1429
|
-
width: options?.width ??
|
|
1430
|
-
height: options?.height ??
|
|
1616
|
+
width: (options?.width ?? 1200).toString(),
|
|
1617
|
+
height: (options?.height ?? 600).toString(),
|
|
1431
1618
|
style: `background-color: ${colorMap.schematic.background}`
|
|
1432
1619
|
},
|
|
1433
1620
|
children: [
|
|
@@ -1446,77 +1633,27 @@ function convertCircuitJsonToSchematicSvg(soup, options) {
|
|
|
1446
1633
|
.pin-number { font-size: 0.15px; fill: ${colorMap.schematic.pin_number}; }
|
|
1447
1634
|
.port-label { fill: ${colorMap.schematic.reference}; }
|
|
1448
1635
|
.component-name { font-size: 0.25px; fill: ${colorMap.schematic.reference}; }
|
|
1449
|
-
|
|
1636
|
+
`,
|
|
1637
|
+
name: "",
|
|
1638
|
+
attributes: {},
|
|
1639
|
+
children: []
|
|
1450
1640
|
}
|
|
1451
|
-
]
|
|
1641
|
+
],
|
|
1642
|
+
value: "",
|
|
1643
|
+
attributes: {}
|
|
1452
1644
|
},
|
|
1453
1645
|
...svgChildren
|
|
1454
|
-
]
|
|
1646
|
+
],
|
|
1647
|
+
value: ""
|
|
1455
1648
|
};
|
|
1456
1649
|
return stringify2({
|
|
1457
|
-
value: "",
|
|
1458
1650
|
...svgObject,
|
|
1459
1651
|
attributes: {
|
|
1460
1652
|
...svgObject.attributes,
|
|
1461
|
-
width: svgObject.attributes.width
|
|
1462
|
-
height: svgObject.attributes.height
|
|
1653
|
+
width: svgObject.attributes.width?.toString(),
|
|
1654
|
+
height: svgObject.attributes.height?.toString()
|
|
1463
1655
|
}
|
|
1464
1656
|
});
|
|
1465
|
-
function createSchematicTrace(trace, flipY2, portPositions2) {
|
|
1466
|
-
const edges = trace.edges;
|
|
1467
|
-
if (edges.length === 0) return null;
|
|
1468
|
-
let path = "";
|
|
1469
|
-
edges.forEach((edge, index) => {
|
|
1470
|
-
const fromPoint = edge.from.ti !== void 0 ? portPositions2.get(edge.from.ti) : edge.from;
|
|
1471
|
-
const toPoint = edge.to.ti !== void 0 ? portPositions2.get(edge.to.ti) : edge.to;
|
|
1472
|
-
if (!fromPoint || !toPoint) {
|
|
1473
|
-
return;
|
|
1474
|
-
}
|
|
1475
|
-
const fromCoord = `${fromPoint.x - 0.15} ${flipY2(fromPoint.y)}`;
|
|
1476
|
-
const toCoord = `${toPoint.x + 0.15} ${flipY2(toPoint.y)}`;
|
|
1477
|
-
if (index === 0) {
|
|
1478
|
-
path += `M ${fromCoord} L ${toCoord}`;
|
|
1479
|
-
} else {
|
|
1480
|
-
path += ` L ${toCoord}`;
|
|
1481
|
-
}
|
|
1482
|
-
});
|
|
1483
|
-
if (trace.to_schematic_port_id) {
|
|
1484
|
-
const finalPort = portPositions2.get(trace.to_schematic_port_id);
|
|
1485
|
-
if (finalPort) {
|
|
1486
|
-
const lastFromPoint = path.split("M")[1]?.split("L")[0];
|
|
1487
|
-
const lastEdge = edges[edges.length - 1];
|
|
1488
|
-
const lastPoint = lastEdge.to.ti !== void 0 ? portPositions2.get(lastEdge.to.ti) : lastEdge.to;
|
|
1489
|
-
if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {
|
|
1490
|
-
const finalCoord = `${finalPort.x} ${flipY2(finalPort.y)}`;
|
|
1491
|
-
path += ` M ${lastFromPoint} L ${finalCoord}`;
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
return path ? {
|
|
1496
|
-
name: "path",
|
|
1497
|
-
type: "element",
|
|
1498
|
-
attributes: {
|
|
1499
|
-
class: "trace",
|
|
1500
|
-
d: path
|
|
1501
|
-
}
|
|
1502
|
-
} : null;
|
|
1503
|
-
}
|
|
1504
|
-
function updateBounds(center, size, rotation) {
|
|
1505
|
-
const corners = [
|
|
1506
|
-
{ x: -size.width / 2, y: -size.height / 2 },
|
|
1507
|
-
{ x: size.width / 2, y: -size.height / 2 },
|
|
1508
|
-
{ x: size.width / 2, y: size.height / 2 },
|
|
1509
|
-
{ x: -size.width / 2, y: size.height / 2 }
|
|
1510
|
-
];
|
|
1511
|
-
for (const corner of corners) {
|
|
1512
|
-
const rotatedX = corner.x * Math.cos(rotation) - corner.y * Math.sin(rotation) + center.x;
|
|
1513
|
-
const rotatedY = corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + center.y;
|
|
1514
|
-
minX = Math.min(minX, rotatedX);
|
|
1515
|
-
minY = Math.min(minY, rotatedY);
|
|
1516
|
-
maxX = Math.max(maxX, rotatedX);
|
|
1517
|
-
maxY = Math.max(maxY, rotatedY);
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
1657
|
}
|
|
1521
1658
|
var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
|
|
1522
1659
|
export {
|