circuit-to-svg 0.0.56 → 0.0.58
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 +606 -382
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -979,9 +979,7 @@ var colorMap = {
|
|
|
979
979
|
// lib/sch/convert-circuit-json-to-schematic-svg.ts
|
|
980
980
|
import { stringify as stringify2 } from "svgson";
|
|
981
981
|
import {
|
|
982
|
-
|
|
983
|
-
scale as scale2,
|
|
984
|
-
translate as translate4
|
|
982
|
+
fromTriangles
|
|
985
983
|
} from "transformation-matrix";
|
|
986
984
|
|
|
987
985
|
// lib/sch/draw-schematic-grid.ts
|
|
@@ -1038,12 +1036,13 @@ function drawSchematicGrid(params) {
|
|
|
1038
1036
|
type: "element",
|
|
1039
1037
|
attributes: {
|
|
1040
1038
|
x: (point.x - 2.5).toString(),
|
|
1041
|
-
y: (point.y -
|
|
1039
|
+
y: (point.y - 5).toString(),
|
|
1042
1040
|
fill: colorMap.schematic.grid,
|
|
1043
1041
|
"font-size": (cellSize / 5 * Math.abs(params.transform.a)).toString(),
|
|
1044
1042
|
"fill-opacity": "0.5",
|
|
1045
1043
|
"text-anchor": "middle",
|
|
1046
|
-
"dominant-baseline": "middle"
|
|
1044
|
+
"dominant-baseline": "middle",
|
|
1045
|
+
"font-family": "sans-serif"
|
|
1047
1046
|
},
|
|
1048
1047
|
children: [
|
|
1049
1048
|
{
|
|
@@ -1167,381 +1166,587 @@ function getSchematicBoundsFromCircuitJson(soup, padding = 0.5) {
|
|
|
1167
1166
|
}
|
|
1168
1167
|
}
|
|
1169
1168
|
|
|
1170
|
-
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component.ts
|
|
1169
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-symbol.ts
|
|
1171
1170
|
import { su } from "@tscircuit/soup-util";
|
|
1172
|
-
import {
|
|
1173
|
-
import
|
|
1174
|
-
import {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1171
|
+
import { symbols } from "schematic-symbols";
|
|
1172
|
+
import "svgson";
|
|
1173
|
+
import {
|
|
1174
|
+
applyToPoint as applyToPoint15,
|
|
1175
|
+
compose as compose5
|
|
1176
|
+
} from "transformation-matrix";
|
|
1177
|
+
|
|
1178
|
+
// lib/utils/get-sch-stroke-size.ts
|
|
1179
|
+
var getSchStrokeSize = (transform) => {
|
|
1180
|
+
return Math.abs(transform.a) * 0.02;
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
// lib/utils/match-sch-ports-with-symbol-ports.ts
|
|
1184
|
+
var getAngularDifference = (angle1, angle2) => {
|
|
1185
|
+
const a1 = angle1 < 0 ? angle1 + 2 * Math.PI : angle1;
|
|
1186
|
+
const a2 = angle2 < 0 ? angle2 + 2 * Math.PI : angle2;
|
|
1187
|
+
let diff = Math.abs(a1 - a2);
|
|
1188
|
+
if (diff > Math.PI) {
|
|
1189
|
+
diff = 2 * Math.PI - diff;
|
|
1190
|
+
}
|
|
1191
|
+
return diff;
|
|
1192
|
+
};
|
|
1193
|
+
var matchSchPortsToSymbolPorts = ({
|
|
1194
|
+
schPorts,
|
|
1195
|
+
symbol,
|
|
1196
|
+
schComponent
|
|
1197
|
+
}) => {
|
|
1198
|
+
const schPortAngles = schPorts.map((port) => {
|
|
1199
|
+
const dx = port.center.x - schComponent.center.x;
|
|
1200
|
+
const dy = port.center.y - schComponent.center.y;
|
|
1201
|
+
return {
|
|
1202
|
+
port,
|
|
1203
|
+
angle: Math.atan2(dy, dx)
|
|
1204
|
+
};
|
|
1205
|
+
});
|
|
1206
|
+
const symbolPortAngles = symbol.ports.map((port) => {
|
|
1207
|
+
const dx = port.x - symbol.center.x;
|
|
1208
|
+
const dy = port.y - symbol.center.y;
|
|
1209
|
+
return {
|
|
1210
|
+
port,
|
|
1211
|
+
angle: Math.atan2(dy, dx)
|
|
1212
|
+
};
|
|
1213
|
+
});
|
|
1214
|
+
schPortAngles.sort((a, b) => a.angle - b.angle);
|
|
1215
|
+
symbolPortAngles.sort((a, b) => a.angle - b.angle);
|
|
1216
|
+
const matches = [];
|
|
1217
|
+
const usedSymbolPorts = /* @__PURE__ */ new Set();
|
|
1218
|
+
for (const schPortAngle of schPortAngles) {
|
|
1219
|
+
let bestMatch = null;
|
|
1220
|
+
for (const symbolPortAngle of symbolPortAngles) {
|
|
1221
|
+
if (usedSymbolPorts.has(symbolPortAngle.port)) continue;
|
|
1222
|
+
const angleDiff = getAngularDifference(
|
|
1223
|
+
schPortAngle.angle,
|
|
1224
|
+
symbolPortAngle.angle
|
|
1225
|
+
);
|
|
1226
|
+
if (bestMatch === null || angleDiff < bestMatch.angleDiff) {
|
|
1227
|
+
bestMatch = {
|
|
1228
|
+
symbolPort: symbolPortAngle.port,
|
|
1229
|
+
angleDiff
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
if (bestMatch && bestMatch.angleDiff < Math.PI / 4) {
|
|
1234
|
+
matches.push({
|
|
1235
|
+
schPort: schPortAngle.port,
|
|
1236
|
+
symbolPort: bestMatch.symbolPort
|
|
1237
|
+
});
|
|
1238
|
+
usedSymbolPorts.add(bestMatch.symbolPort);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return matches;
|
|
1242
|
+
};
|
|
1243
|
+
|
|
1244
|
+
// lib/utils/point-pairs-to-matrix.ts
|
|
1245
|
+
import { compose as compose4, scale as scale2, translate as translate4 } from "transformation-matrix";
|
|
1246
|
+
function pointPairsToMatrix(a1, a2, b1, b2) {
|
|
1247
|
+
const tx = a2.x - a1.x;
|
|
1248
|
+
const ty = a2.y - a1.y;
|
|
1249
|
+
const originalDistance = Math.sqrt((b1.x - a1.x) ** 2 + (b1.y - a1.y) ** 2);
|
|
1250
|
+
const transformedDistance = Math.sqrt((b2.x - a2.x) ** 2 + (b2.y - a2.y) ** 2);
|
|
1251
|
+
const a = transformedDistance / originalDistance;
|
|
1252
|
+
const translateMatrix = translate4(tx, ty);
|
|
1253
|
+
const scaleMatrix = scale2(a, a);
|
|
1254
|
+
return compose4(translateMatrix, scaleMatrix);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
// lib/utils/get-sch-font-size.ts
|
|
1258
|
+
import "transformation-matrix";
|
|
1259
|
+
var getSchFontSize = (transform, textType) => {
|
|
1260
|
+
return Math.abs(transform.a) * (textType === "pin_number" ? 0.15 : 0.18);
|
|
1261
|
+
};
|
|
1262
|
+
|
|
1263
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-symbol.ts
|
|
1264
|
+
var ninePointAnchorToTextAnchor = {
|
|
1265
|
+
top_left: "start",
|
|
1266
|
+
top_right: "end",
|
|
1267
|
+
middle_left: "start",
|
|
1268
|
+
middle_right: "end",
|
|
1269
|
+
bottom_left: "start",
|
|
1270
|
+
bottom_right: "end",
|
|
1271
|
+
center: "middle",
|
|
1272
|
+
middle_top: "middle",
|
|
1273
|
+
middle_bottom: "middle"
|
|
1274
|
+
};
|
|
1275
|
+
var ninePointAnchorToDominantBaseline = {
|
|
1276
|
+
top_left: "auto",
|
|
1277
|
+
top_right: "auto",
|
|
1278
|
+
bottom_left: "hanging",
|
|
1279
|
+
bottom_right: "hanging",
|
|
1280
|
+
center: "auto",
|
|
1281
|
+
middle_left: "middle",
|
|
1282
|
+
middle_right: "middle",
|
|
1283
|
+
middle_top: "auto",
|
|
1284
|
+
middle_bottom: "hanging"
|
|
1285
|
+
};
|
|
1286
|
+
var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
1287
|
+
component: schComponent,
|
|
1288
|
+
transform: realToScreenTransform,
|
|
1178
1289
|
circuitJson
|
|
1179
|
-
}) {
|
|
1180
|
-
const
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
const componentScale = Math.abs(transform.a);
|
|
1189
|
-
let componentChildren = [];
|
|
1190
|
-
const textChildren = [];
|
|
1191
|
-
const sourceComponent = circuitJson?.find(
|
|
1192
|
-
(item) => item.type === "source_component" && item.source_component_id === sourceComponentId
|
|
1290
|
+
}) => {
|
|
1291
|
+
const svgObjects = [];
|
|
1292
|
+
const symbol = symbols[schComponent.symbol_name];
|
|
1293
|
+
if (!symbol) return [];
|
|
1294
|
+
const schPorts = su(circuitJson).schematic_port.list({
|
|
1295
|
+
schematic_component_id: schComponent.schematic_component_id
|
|
1296
|
+
});
|
|
1297
|
+
const srcComponent = su(circuitJson).source_component.get(
|
|
1298
|
+
schComponent.source_component_id
|
|
1193
1299
|
);
|
|
1194
|
-
const
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1300
|
+
const schPortsWithSymbolPorts = matchSchPortsToSymbolPorts({
|
|
1301
|
+
schPorts,
|
|
1302
|
+
symbol,
|
|
1303
|
+
schComponent
|
|
1304
|
+
});
|
|
1305
|
+
if (!schPortsWithSymbolPorts[0]) return [];
|
|
1306
|
+
const transformFromSymbolToReal = pointPairsToMatrix(
|
|
1307
|
+
schPortsWithSymbolPorts[1]?.symbolPort ?? symbol.center,
|
|
1308
|
+
schPortsWithSymbolPorts[1]?.schPort.center ?? schComponent.center,
|
|
1309
|
+
schPortsWithSymbolPorts[0].symbolPort,
|
|
1310
|
+
schPortsWithSymbolPorts[0].schPort.center
|
|
1311
|
+
);
|
|
1312
|
+
const paths = symbol.primitives.filter((p) => p.type === "path");
|
|
1313
|
+
const texts = symbol.primitives.filter((p) => p.type === "text");
|
|
1314
|
+
const circles = symbol.primitives.filter((p) => p.type === "circle");
|
|
1315
|
+
const boxes = symbol.primitives.filter((p) => p.type === "box");
|
|
1316
|
+
for (const path of paths) {
|
|
1317
|
+
const { points, color, closed, fill } = path;
|
|
1318
|
+
svgObjects.push({
|
|
1319
|
+
type: "element",
|
|
1320
|
+
name: "path",
|
|
1321
|
+
attributes: {
|
|
1322
|
+
d: points.map((p, i) => {
|
|
1323
|
+
const [x, y] = applyToPoint15(
|
|
1324
|
+
compose5(realToScreenTransform, transformFromSymbolToReal),
|
|
1325
|
+
[p.x, p.y]
|
|
1326
|
+
);
|
|
1327
|
+
return `${i === 0 ? "M" : "L"} ${x} ${y}`;
|
|
1328
|
+
}).join(" ") + (closed ? " Z" : ""),
|
|
1329
|
+
stroke: colorMap.schematic.component_outline,
|
|
1330
|
+
fill: "none",
|
|
1331
|
+
"stroke-width": `${getSchStrokeSize(realToScreenTransform)}px`
|
|
1332
|
+
},
|
|
1333
|
+
value: "",
|
|
1334
|
+
children: []
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
for (const text of texts) {
|
|
1338
|
+
const screenTextPos = applyToPoint15(
|
|
1339
|
+
compose5(realToScreenTransform, transformFromSymbolToReal),
|
|
1340
|
+
text
|
|
1210
1341
|
);
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1342
|
+
let textValue = "";
|
|
1343
|
+
if (text.text === "{REF}") {
|
|
1344
|
+
textValue = srcComponent?.name ?? "";
|
|
1345
|
+
} else if (text.text === "{VAL}") {
|
|
1346
|
+
textValue = srcComponent?.display_value ?? srcComponent.capacitance ?? srcComponent.resistance;
|
|
1347
|
+
}
|
|
1348
|
+
svgObjects.push({
|
|
1349
|
+
name: "text",
|
|
1350
|
+
type: "element",
|
|
1351
|
+
attributes: {
|
|
1352
|
+
x: screenTextPos.x.toString(),
|
|
1353
|
+
y: screenTextPos.y.toString(),
|
|
1354
|
+
"dominant-baseline": ninePointAnchorToDominantBaseline[text.anchor],
|
|
1355
|
+
"text-anchor": ninePointAnchorToTextAnchor[text.anchor],
|
|
1356
|
+
"font-family": "sans-serif",
|
|
1357
|
+
"font-size": `${getSchFontSize(realToScreenTransform, "reference_designator")}px`
|
|
1358
|
+
},
|
|
1359
|
+
value: "",
|
|
1360
|
+
children: [
|
|
1361
|
+
{
|
|
1362
|
+
type: "text",
|
|
1363
|
+
value: textValue,
|
|
1364
|
+
name: "",
|
|
1365
|
+
attributes: {},
|
|
1366
|
+
children: []
|
|
1223
1367
|
}
|
|
1224
|
-
|
|
1368
|
+
]
|
|
1225
1369
|
});
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
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
|
-
}
|
|
1277
|
-
} else {
|
|
1278
|
-
componentChildren.push({
|
|
1370
|
+
}
|
|
1371
|
+
for (const box of boxes) {
|
|
1372
|
+
const screenBoxPos = applyToPoint15(
|
|
1373
|
+
compose5(realToScreenTransform, transformFromSymbolToReal),
|
|
1374
|
+
box
|
|
1375
|
+
);
|
|
1376
|
+
const symbolToScreenScale = compose5(
|
|
1377
|
+
realToScreenTransform,
|
|
1378
|
+
transformFromSymbolToReal
|
|
1379
|
+
).a;
|
|
1380
|
+
svgObjects.push({
|
|
1279
1381
|
name: "rect",
|
|
1280
1382
|
type: "element",
|
|
1281
|
-
value: "",
|
|
1282
1383
|
attributes: {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
"stroke-width": "0.02"
|
|
1384
|
+
x: screenBoxPos.x.toString(),
|
|
1385
|
+
y: screenBoxPos.y.toString(),
|
|
1386
|
+
width: (box.width * symbolToScreenScale).toString(),
|
|
1387
|
+
height: (box.height * symbolToScreenScale).toString(),
|
|
1388
|
+
fill: "red"
|
|
1289
1389
|
},
|
|
1390
|
+
value: "",
|
|
1290
1391
|
children: []
|
|
1291
1392
|
});
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
"font-size": "0.2"
|
|
1311
|
-
},
|
|
1312
|
-
children: [
|
|
1313
|
-
{
|
|
1314
|
-
type: "text",
|
|
1315
|
-
value: manufacturerNumber,
|
|
1316
|
-
name: "",
|
|
1317
|
-
attributes: {},
|
|
1318
|
-
children: []
|
|
1319
|
-
}
|
|
1320
|
-
],
|
|
1321
|
-
value: ""
|
|
1322
|
-
});
|
|
1323
|
-
textChildren.push({
|
|
1324
|
-
name: "text",
|
|
1325
|
-
type: "element",
|
|
1326
|
-
attributes: {
|
|
1327
|
-
class: "component-name",
|
|
1328
|
-
x: textX.toString(),
|
|
1329
|
-
y: (textY - labelOffset).toString(),
|
|
1330
|
-
"text-anchor": "right",
|
|
1331
|
-
// Center align text
|
|
1332
|
-
"dominant-baseline": "auto",
|
|
1333
|
-
"font-size": "0.2"
|
|
1334
|
-
},
|
|
1335
|
-
children: [
|
|
1336
|
-
{
|
|
1337
|
-
type: "text",
|
|
1338
|
-
value: componentName || "",
|
|
1339
|
-
name: "",
|
|
1340
|
-
attributes: {},
|
|
1341
|
-
children: []
|
|
1342
|
-
}
|
|
1343
|
-
],
|
|
1344
|
-
value: ""
|
|
1345
|
-
});
|
|
1346
|
-
}
|
|
1347
|
-
const schematicPorts = su(circuitJson).schematic_port.list({
|
|
1348
|
-
schematic_component_id: schematicComponentId
|
|
1393
|
+
}
|
|
1394
|
+
for (const port of symbol.ports) {
|
|
1395
|
+
const screenPortPos = applyToPoint15(
|
|
1396
|
+
compose5(realToScreenTransform, transformFromSymbolToReal),
|
|
1397
|
+
port
|
|
1398
|
+
);
|
|
1399
|
+
svgObjects.push({
|
|
1400
|
+
type: "element",
|
|
1401
|
+
name: "circle",
|
|
1402
|
+
attributes: {
|
|
1403
|
+
cx: screenPortPos.x.toString(),
|
|
1404
|
+
cy: screenPortPos.y.toString(),
|
|
1405
|
+
r: `${realToScreenTransform.a * 0.02}px`,
|
|
1406
|
+
fill: "none",
|
|
1407
|
+
stroke: colorMap.schematic.component_outline
|
|
1408
|
+
},
|
|
1409
|
+
value: "",
|
|
1410
|
+
children: []
|
|
1349
1411
|
});
|
|
1350
|
-
const portLength = 0.2;
|
|
1351
|
-
const circleRadius = 0.05;
|
|
1352
|
-
for (const schPort of schematicPorts) {
|
|
1353
|
-
const { x: portX, y: portY } = schPort.center;
|
|
1354
|
-
const srcPort = su(circuitJson).source_port.get(
|
|
1355
|
-
schPort.source_port_id
|
|
1356
|
-
);
|
|
1357
|
-
const pinNumber = srcPort?.pin_number;
|
|
1358
|
-
const relX = portX - center.x;
|
|
1359
|
-
const relY = portY - center.y;
|
|
1360
|
-
let endX = relX;
|
|
1361
|
-
let endY = relY;
|
|
1362
|
-
const portSide = schPort.side ?? schPort.center.side;
|
|
1363
|
-
if (portSide === "center") {
|
|
1364
|
-
continue;
|
|
1365
|
-
}
|
|
1366
|
-
switch (portSide) {
|
|
1367
|
-
case "left":
|
|
1368
|
-
endX = relX + portLength;
|
|
1369
|
-
break;
|
|
1370
|
-
case "right":
|
|
1371
|
-
endX = relX - portLength;
|
|
1372
|
-
break;
|
|
1373
|
-
case "top":
|
|
1374
|
-
endY = relY + portLength;
|
|
1375
|
-
break;
|
|
1376
|
-
case "bottom":
|
|
1377
|
-
endY = relY - portLength;
|
|
1378
|
-
break;
|
|
1379
|
-
}
|
|
1380
|
-
componentChildren.push({
|
|
1381
|
-
name: "line",
|
|
1382
|
-
type: "element",
|
|
1383
|
-
attributes: {
|
|
1384
|
-
class: "component-pin",
|
|
1385
|
-
x1: relX.toString(),
|
|
1386
|
-
y1: relY.toString(),
|
|
1387
|
-
x2: endX.toString(),
|
|
1388
|
-
y2: endY.toString(),
|
|
1389
|
-
"stroke-width": "0.02"
|
|
1390
|
-
},
|
|
1391
|
-
value: "",
|
|
1392
|
-
children: []
|
|
1393
|
-
});
|
|
1394
|
-
componentChildren.push({
|
|
1395
|
-
name: "circle",
|
|
1396
|
-
type: "element",
|
|
1397
|
-
attributes: {
|
|
1398
|
-
class: "component-pin",
|
|
1399
|
-
cx: relX.toString(),
|
|
1400
|
-
cy: relY.toString(),
|
|
1401
|
-
r: circleRadius.toString(),
|
|
1402
|
-
"stroke-width": "0.02"
|
|
1403
|
-
},
|
|
1404
|
-
value: "",
|
|
1405
|
-
children: []
|
|
1406
|
-
});
|
|
1407
|
-
const [portEndX, portEndY] = applyToPoint14(transform, [
|
|
1408
|
-
center.x + endX,
|
|
1409
|
-
center.y + endY
|
|
1410
|
-
]);
|
|
1411
|
-
const labelKey = `pin${pinNumber}`;
|
|
1412
|
-
if (portLabels && labelKey in portLabels) {
|
|
1413
|
-
const labelText = portLabels[labelKey];
|
|
1414
|
-
let labelX = portEndX;
|
|
1415
|
-
let labelY = portEndY;
|
|
1416
|
-
let textAnchor = "middle";
|
|
1417
|
-
let rotation2 = 0;
|
|
1418
|
-
const labelOffset = 0.1 * componentScale;
|
|
1419
|
-
switch (portSide) {
|
|
1420
|
-
case "left":
|
|
1421
|
-
labelX += labelOffset;
|
|
1422
|
-
textAnchor = "start";
|
|
1423
|
-
break;
|
|
1424
|
-
case "right":
|
|
1425
|
-
labelX -= labelOffset;
|
|
1426
|
-
textAnchor = "end";
|
|
1427
|
-
break;
|
|
1428
|
-
case "top":
|
|
1429
|
-
labelY += labelOffset * 6;
|
|
1430
|
-
textAnchor = "start";
|
|
1431
|
-
rotation2 = -90;
|
|
1432
|
-
break;
|
|
1433
|
-
case "bottom":
|
|
1434
|
-
labelY -= labelOffset * 6;
|
|
1435
|
-
textAnchor = "end";
|
|
1436
|
-
rotation2 = -90;
|
|
1437
|
-
break;
|
|
1438
|
-
}
|
|
1439
|
-
textChildren.push({
|
|
1440
|
-
name: "text",
|
|
1441
|
-
type: "element",
|
|
1442
|
-
attributes: {
|
|
1443
|
-
class: "port-label",
|
|
1444
|
-
x: labelX.toString(),
|
|
1445
|
-
y: labelY.toString(),
|
|
1446
|
-
"text-anchor": textAnchor,
|
|
1447
|
-
"dominant-baseline": "middle",
|
|
1448
|
-
"font-size": (0.2 * componentScale).toString(),
|
|
1449
|
-
transform: rotation2 ? `rotate(${rotation2}, ${labelX}, ${labelY})` : ""
|
|
1450
|
-
},
|
|
1451
|
-
children: [
|
|
1452
|
-
{
|
|
1453
|
-
type: "text",
|
|
1454
|
-
value: labelText,
|
|
1455
|
-
name: "",
|
|
1456
|
-
attributes: {},
|
|
1457
|
-
children: []
|
|
1458
|
-
}
|
|
1459
|
-
],
|
|
1460
|
-
value: ""
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
const pinNumberOffset = 0.2;
|
|
1464
|
-
let pinX = endX;
|
|
1465
|
-
let pinY = endY;
|
|
1466
|
-
let dominantBaseline = "auto";
|
|
1467
|
-
switch (portSide) {
|
|
1468
|
-
case "top":
|
|
1469
|
-
pinY = portY - pinNumberOffset;
|
|
1470
|
-
pinX = portX;
|
|
1471
|
-
dominantBaseline = "auto";
|
|
1472
|
-
break;
|
|
1473
|
-
case "bottom":
|
|
1474
|
-
pinY = portY + pinNumberOffset;
|
|
1475
|
-
pinX = portX;
|
|
1476
|
-
dominantBaseline = "hanging";
|
|
1477
|
-
break;
|
|
1478
|
-
case "left":
|
|
1479
|
-
pinX = portX - pinNumberOffset;
|
|
1480
|
-
pinY = portY + pinNumberOffset / 4;
|
|
1481
|
-
dominantBaseline = "auto";
|
|
1482
|
-
break;
|
|
1483
|
-
case "right":
|
|
1484
|
-
pinX = portX + pinNumberOffset;
|
|
1485
|
-
pinY = portY + pinNumberOffset / 4;
|
|
1486
|
-
dominantBaseline = "auto";
|
|
1487
|
-
break;
|
|
1488
|
-
}
|
|
1489
|
-
const [transformedPinX, transformedPinY] = applyToPoint14(transform, [
|
|
1490
|
-
pinX,
|
|
1491
|
-
pinY
|
|
1492
|
-
]);
|
|
1493
|
-
textChildren.push({
|
|
1494
|
-
name: "text",
|
|
1495
|
-
type: "element",
|
|
1496
|
-
attributes: {
|
|
1497
|
-
class: "pin-number",
|
|
1498
|
-
x: transformedPinX.toString(),
|
|
1499
|
-
y: transformedPinY.toString(),
|
|
1500
|
-
"text-anchor": "middle",
|
|
1501
|
-
"dominant-baseline": dominantBaseline,
|
|
1502
|
-
"font-size": (0.15 * componentScale).toString()
|
|
1503
|
-
},
|
|
1504
|
-
children: [
|
|
1505
|
-
{
|
|
1506
|
-
type: "text",
|
|
1507
|
-
value: pinNumber?.toString() || "",
|
|
1508
|
-
name: "",
|
|
1509
|
-
attributes: {},
|
|
1510
|
-
children: []
|
|
1511
|
-
}
|
|
1512
|
-
],
|
|
1513
|
-
value: ""
|
|
1514
|
-
});
|
|
1515
|
-
}
|
|
1516
1412
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1413
|
+
return svgObjects;
|
|
1414
|
+
};
|
|
1415
|
+
|
|
1416
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-box.ts
|
|
1417
|
+
import { su as su4 } from "@tscircuit/soup-util";
|
|
1418
|
+
import "schematic-symbols";
|
|
1419
|
+
import "svgson";
|
|
1420
|
+
import { applyToPoint as applyToPoint20 } from "transformation-matrix";
|
|
1421
|
+
|
|
1422
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-port-on-box.ts
|
|
1423
|
+
import "transformation-matrix";
|
|
1424
|
+
import "@tscircuit/soup-util";
|
|
1425
|
+
|
|
1426
|
+
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-box-line.ts
|
|
1427
|
+
import { applyToPoint as applyToPoint16 } from "transformation-matrix";
|
|
1428
|
+
import { su as su2 } from "@tscircuit/soup-util";
|
|
1429
|
+
var PIN_CIRCLE_RADIUS_MM = 0.02;
|
|
1430
|
+
var createSvgObjectsForSchPortBoxLine = ({
|
|
1431
|
+
schPort,
|
|
1432
|
+
schComponent,
|
|
1433
|
+
transform,
|
|
1434
|
+
circuitJson
|
|
1435
|
+
}) => {
|
|
1436
|
+
const svgObjects = [];
|
|
1437
|
+
const srcPort = su2(circuitJson).source_port.get(schPort.source_port_id);
|
|
1438
|
+
const realEdgePos = {
|
|
1439
|
+
x: schPort.center.x,
|
|
1440
|
+
y: schPort.center.y
|
|
1441
|
+
};
|
|
1442
|
+
const realPinLineLength = schPort.distance_from_component_edge ?? 0.4;
|
|
1443
|
+
switch (schPort.side_of_component) {
|
|
1444
|
+
case "left":
|
|
1445
|
+
realEdgePos.x += realPinLineLength;
|
|
1446
|
+
break;
|
|
1447
|
+
case "right":
|
|
1448
|
+
realEdgePos.x -= realPinLineLength;
|
|
1449
|
+
break;
|
|
1450
|
+
case "top":
|
|
1451
|
+
realEdgePos.y -= realPinLineLength;
|
|
1452
|
+
break;
|
|
1453
|
+
case "bottom":
|
|
1454
|
+
realEdgePos.y += realPinLineLength;
|
|
1455
|
+
break;
|
|
1456
|
+
}
|
|
1457
|
+
const screenSchPortPos = applyToPoint16(transform, schPort.center);
|
|
1458
|
+
const screenRealEdgePos = applyToPoint16(transform, realEdgePos);
|
|
1459
|
+
const realLineEnd = { ...schPort.center };
|
|
1460
|
+
switch (schPort.side_of_component) {
|
|
1461
|
+
case "left":
|
|
1462
|
+
realLineEnd.x += PIN_CIRCLE_RADIUS_MM;
|
|
1463
|
+
break;
|
|
1464
|
+
case "right":
|
|
1465
|
+
realLineEnd.x -= PIN_CIRCLE_RADIUS_MM;
|
|
1466
|
+
break;
|
|
1467
|
+
case "top":
|
|
1468
|
+
realLineEnd.y -= PIN_CIRCLE_RADIUS_MM;
|
|
1469
|
+
break;
|
|
1470
|
+
case "bottom":
|
|
1471
|
+
realLineEnd.y += PIN_CIRCLE_RADIUS_MM;
|
|
1472
|
+
break;
|
|
1473
|
+
}
|
|
1474
|
+
const screenLineEnd = applyToPoint16(transform, realLineEnd);
|
|
1475
|
+
svgObjects.push({
|
|
1476
|
+
name: "line",
|
|
1477
|
+
type: "element",
|
|
1478
|
+
attributes: {
|
|
1479
|
+
class: "component-pin",
|
|
1480
|
+
x1: screenLineEnd.x.toString(),
|
|
1481
|
+
y1: screenLineEnd.y.toString(),
|
|
1482
|
+
x2: screenRealEdgePos.x.toString(),
|
|
1483
|
+
y2: screenRealEdgePos.y.toString(),
|
|
1484
|
+
"stroke-width": `${getSchStrokeSize(transform)}px`
|
|
1485
|
+
},
|
|
1519
1486
|
value: "",
|
|
1487
|
+
children: []
|
|
1488
|
+
});
|
|
1489
|
+
svgObjects.push({
|
|
1490
|
+
name: "circle",
|
|
1520
1491
|
type: "element",
|
|
1521
1492
|
attributes: {
|
|
1522
|
-
|
|
1493
|
+
class: "component-pin",
|
|
1494
|
+
cx: screenSchPortPos.x.toString(),
|
|
1495
|
+
cy: screenSchPortPos.y.toString(),
|
|
1496
|
+
r: (Math.abs(transform.a) * PIN_CIRCLE_RADIUS_MM).toString(),
|
|
1497
|
+
"stroke-width": `${getSchStrokeSize(transform)}px`
|
|
1523
1498
|
},
|
|
1524
|
-
children: componentChildren
|
|
1525
|
-
};
|
|
1526
|
-
const textGroup = {
|
|
1527
|
-
name: "g",
|
|
1528
1499
|
value: "",
|
|
1500
|
+
children: []
|
|
1501
|
+
});
|
|
1502
|
+
return svgObjects;
|
|
1503
|
+
};
|
|
1504
|
+
|
|
1505
|
+
// lib/utils/get-unit-vector-from-outside-to-edge.ts
|
|
1506
|
+
var getUnitVectorFromOutsideToEdge = (side) => {
|
|
1507
|
+
switch (side) {
|
|
1508
|
+
case "top":
|
|
1509
|
+
return { x: 0, y: -1 };
|
|
1510
|
+
case "bottom":
|
|
1511
|
+
return { x: 0, y: 1 };
|
|
1512
|
+
case "left":
|
|
1513
|
+
return { x: 1, y: 0 };
|
|
1514
|
+
case "right":
|
|
1515
|
+
return { x: -1, y: 0 };
|
|
1516
|
+
}
|
|
1517
|
+
throw new Error(`Invalid side: ${side}`);
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-pin-number-text.ts
|
|
1521
|
+
import { applyToPoint as applyToPoint17 } from "transformation-matrix";
|
|
1522
|
+
var createSvgObjectsForSchPortPinNumberText = (params) => {
|
|
1523
|
+
const svgObjects = [];
|
|
1524
|
+
const { schPort, schComponent, transform, circuitJson } = params;
|
|
1525
|
+
const realPinNumberPos = {
|
|
1526
|
+
x: schPort.center.x,
|
|
1527
|
+
y: schPort.center.y
|
|
1528
|
+
};
|
|
1529
|
+
if (!schPort.side_of_component) return [];
|
|
1530
|
+
const vecToEdge = getUnitVectorFromOutsideToEdge(schPort.side_of_component);
|
|
1531
|
+
const realPinEdgeDistance = schPort.distance_from_component_edge ?? 0.4;
|
|
1532
|
+
realPinNumberPos.x += vecToEdge.x * realPinEdgeDistance / 2;
|
|
1533
|
+
realPinNumberPos.y += vecToEdge.y * realPinEdgeDistance / 2;
|
|
1534
|
+
const screenPinNumberTextPos = applyToPoint17(transform, realPinNumberPos);
|
|
1535
|
+
if (schPort.side_of_component === "top" || schPort.side_of_component === "bottom") {
|
|
1536
|
+
screenPinNumberTextPos.x -= 2;
|
|
1537
|
+
} else {
|
|
1538
|
+
screenPinNumberTextPos.y -= 2;
|
|
1539
|
+
}
|
|
1540
|
+
svgObjects.push({
|
|
1541
|
+
name: "text",
|
|
1529
1542
|
type: "element",
|
|
1530
|
-
attributes: {
|
|
1531
|
-
|
|
1543
|
+
attributes: {
|
|
1544
|
+
class: "pin-number",
|
|
1545
|
+
x: screenPinNumberTextPos.x.toString(),
|
|
1546
|
+
y: screenPinNumberTextPos.y.toString(),
|
|
1547
|
+
style: "font-family: sans-serif;",
|
|
1548
|
+
fill: colorMap.schematic.pin_number,
|
|
1549
|
+
"text-anchor": "middle",
|
|
1550
|
+
"dominant-baseline": "auto",
|
|
1551
|
+
"font-size": `${getSchFontSize(transform, "pin_number")}px`,
|
|
1552
|
+
transform: schPort.side_of_component === "top" || schPort.side_of_component === "bottom" ? `rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})` : ""
|
|
1553
|
+
},
|
|
1554
|
+
children: [
|
|
1555
|
+
{
|
|
1556
|
+
type: "text",
|
|
1557
|
+
value: schPort.pin_number?.toString() || "",
|
|
1558
|
+
name: "",
|
|
1559
|
+
attributes: {},
|
|
1560
|
+
children: []
|
|
1561
|
+
}
|
|
1562
|
+
],
|
|
1563
|
+
value: ""
|
|
1564
|
+
});
|
|
1565
|
+
return svgObjects;
|
|
1566
|
+
};
|
|
1567
|
+
|
|
1568
|
+
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-pin-label.ts
|
|
1569
|
+
import { applyToPoint as applyToPoint18 } from "transformation-matrix";
|
|
1570
|
+
var LABEL_DIST_FROM_EDGE_MM = 0.1;
|
|
1571
|
+
var createSvgObjectsForSchPortPinLabel = (params) => {
|
|
1572
|
+
const svgObjects = [];
|
|
1573
|
+
const { schPort, schComponent, transform, circuitJson } = params;
|
|
1574
|
+
const realPinNumberPos = {
|
|
1575
|
+
x: schPort.center.x,
|
|
1576
|
+
y: schPort.center.y
|
|
1532
1577
|
};
|
|
1533
|
-
return [
|
|
1578
|
+
if (!schPort.side_of_component) return [];
|
|
1579
|
+
const vecToEdge = getUnitVectorFromOutsideToEdge(schPort.side_of_component);
|
|
1580
|
+
const realPinEdgeDistance = schPort.distance_from_component_edge ?? 0.4;
|
|
1581
|
+
realPinNumberPos.x += vecToEdge.x * (realPinEdgeDistance + LABEL_DIST_FROM_EDGE_MM);
|
|
1582
|
+
realPinNumberPos.y += vecToEdge.y * (realPinEdgeDistance + LABEL_DIST_FROM_EDGE_MM);
|
|
1583
|
+
const screenPinNumberTextPos = applyToPoint18(transform, realPinNumberPos);
|
|
1584
|
+
const label = schComponent.port_labels?.[`pin${schPort.pin_number}`];
|
|
1585
|
+
if (!label) return [];
|
|
1586
|
+
svgObjects.push({
|
|
1587
|
+
name: "text",
|
|
1588
|
+
type: "element",
|
|
1589
|
+
attributes: {
|
|
1590
|
+
class: "pin-number",
|
|
1591
|
+
x: screenPinNumberTextPos.x.toString(),
|
|
1592
|
+
y: screenPinNumberTextPos.y.toString(),
|
|
1593
|
+
style: "font-family: sans-serif;",
|
|
1594
|
+
fill: colorMap.schematic.pin_number,
|
|
1595
|
+
"text-anchor": schPort.side_of_component === "left" ? "start" : "end",
|
|
1596
|
+
"dominant-baseline": "middle",
|
|
1597
|
+
"font-size": `${getSchFontSize(transform, "pin_number")}px`,
|
|
1598
|
+
transform: schPort.side_of_component === "top" || schPort.side_of_component === "bottom" ? `rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})` : ""
|
|
1599
|
+
},
|
|
1600
|
+
children: [
|
|
1601
|
+
{
|
|
1602
|
+
type: "text",
|
|
1603
|
+
value: label || "",
|
|
1604
|
+
name: "",
|
|
1605
|
+
attributes: {},
|
|
1606
|
+
children: []
|
|
1607
|
+
}
|
|
1608
|
+
],
|
|
1609
|
+
value: ""
|
|
1610
|
+
});
|
|
1611
|
+
return svgObjects;
|
|
1612
|
+
};
|
|
1613
|
+
|
|
1614
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-port-on-box.ts
|
|
1615
|
+
var createSvgObjectsFromSchPortOnBox = (params) => {
|
|
1616
|
+
const svgObjects = [];
|
|
1617
|
+
const { schPort, schComponent, transform, circuitJson } = params;
|
|
1618
|
+
svgObjects.push(...createSvgObjectsForSchPortBoxLine(params));
|
|
1619
|
+
svgObjects.push(...createSvgObjectsForSchPortPinNumberText(params));
|
|
1620
|
+
svgObjects.push(...createSvgObjectsForSchPortPinLabel(params));
|
|
1621
|
+
return svgObjects;
|
|
1622
|
+
};
|
|
1623
|
+
|
|
1624
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-box.ts
|
|
1625
|
+
var createSvgObjectsFromSchematicComponentWithBox = ({
|
|
1626
|
+
component: schComponent,
|
|
1627
|
+
transform,
|
|
1628
|
+
circuitJson
|
|
1629
|
+
}) => {
|
|
1630
|
+
const srcComponent = su4(circuitJson).source_component.get(
|
|
1631
|
+
schComponent.source_component_id
|
|
1632
|
+
);
|
|
1633
|
+
const svgObjects = [];
|
|
1634
|
+
const componentScreenTopLeft = applyToPoint20(transform, {
|
|
1635
|
+
x: schComponent.center.x - schComponent.size.width / 2,
|
|
1636
|
+
y: schComponent.center.y + schComponent.size.height / 2
|
|
1637
|
+
});
|
|
1638
|
+
const componentScreenBottomRight = applyToPoint20(transform, {
|
|
1639
|
+
x: schComponent.center.x + schComponent.size.width / 2,
|
|
1640
|
+
y: schComponent.center.y - schComponent.size.height / 2
|
|
1641
|
+
});
|
|
1642
|
+
const componentScreenWidth = componentScreenBottomRight.x - componentScreenTopLeft.x;
|
|
1643
|
+
const componentScreenHeight = componentScreenBottomRight.y - componentScreenTopLeft.y;
|
|
1644
|
+
svgObjects.push({
|
|
1645
|
+
name: "rect",
|
|
1646
|
+
type: "element",
|
|
1647
|
+
value: "",
|
|
1648
|
+
attributes: {
|
|
1649
|
+
class: "component chip",
|
|
1650
|
+
x: componentScreenTopLeft.x.toString(),
|
|
1651
|
+
y: componentScreenTopLeft.y.toString(),
|
|
1652
|
+
width: componentScreenWidth.toString(),
|
|
1653
|
+
height: componentScreenHeight.toString(),
|
|
1654
|
+
"stroke-width": `${getSchStrokeSize(transform)}px`
|
|
1655
|
+
},
|
|
1656
|
+
children: []
|
|
1657
|
+
});
|
|
1658
|
+
const screenManufacturerNumberPos = applyToPoint20(transform, {
|
|
1659
|
+
x: schComponent.center.x + schComponent.size.width / 2,
|
|
1660
|
+
y: schComponent.center.y + schComponent.size.height / 2 + 0.5
|
|
1661
|
+
// Above the component top edge
|
|
1662
|
+
});
|
|
1663
|
+
const fontSizePx = getSchFontSize(transform, "manufacturer_number");
|
|
1664
|
+
if (srcComponent?.manufacturer_part_number) {
|
|
1665
|
+
svgObjects.push({
|
|
1666
|
+
name: "text",
|
|
1667
|
+
type: "element",
|
|
1668
|
+
attributes: {
|
|
1669
|
+
class: "component-name",
|
|
1670
|
+
x: screenManufacturerNumberPos.x.toString(),
|
|
1671
|
+
y: screenManufacturerNumberPos.y.toString(),
|
|
1672
|
+
"font-family": "sans-serif",
|
|
1673
|
+
"text-anchor": "right",
|
|
1674
|
+
// Center align text
|
|
1675
|
+
"dominant-baseline": "auto",
|
|
1676
|
+
"font-size": `${fontSizePx}px`
|
|
1677
|
+
},
|
|
1678
|
+
children: [
|
|
1679
|
+
{
|
|
1680
|
+
type: "text",
|
|
1681
|
+
value: srcComponent.manufacturer_part_number,
|
|
1682
|
+
name: "",
|
|
1683
|
+
attributes: {},
|
|
1684
|
+
children: []
|
|
1685
|
+
}
|
|
1686
|
+
],
|
|
1687
|
+
value: ""
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
if (srcComponent?.name) {
|
|
1691
|
+
svgObjects.push({
|
|
1692
|
+
name: "text",
|
|
1693
|
+
type: "element",
|
|
1694
|
+
attributes: {
|
|
1695
|
+
class: "component-name",
|
|
1696
|
+
x: screenManufacturerNumberPos.x.toString(),
|
|
1697
|
+
y: (screenManufacturerNumberPos.y + fontSizePx * 1.1).toString(),
|
|
1698
|
+
"font-family": "sans-serif",
|
|
1699
|
+
"text-anchor": "right",
|
|
1700
|
+
// Center align text
|
|
1701
|
+
"dominant-baseline": "auto",
|
|
1702
|
+
"font-size": `${fontSizePx}px`
|
|
1703
|
+
},
|
|
1704
|
+
children: [
|
|
1705
|
+
{
|
|
1706
|
+
type: "text",
|
|
1707
|
+
value: srcComponent.name || "",
|
|
1708
|
+
name: "",
|
|
1709
|
+
attributes: {},
|
|
1710
|
+
children: []
|
|
1711
|
+
}
|
|
1712
|
+
],
|
|
1713
|
+
value: ""
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
const schematicPorts = su4(circuitJson).schematic_port.list({
|
|
1717
|
+
schematic_component_id: schComponent.schematic_component_id
|
|
1718
|
+
});
|
|
1719
|
+
for (const schPort of schematicPorts) {
|
|
1720
|
+
svgObjects.push(
|
|
1721
|
+
...createSvgObjectsFromSchPortOnBox({
|
|
1722
|
+
schPort,
|
|
1723
|
+
schComponent,
|
|
1724
|
+
transform,
|
|
1725
|
+
circuitJson
|
|
1726
|
+
})
|
|
1727
|
+
);
|
|
1728
|
+
}
|
|
1729
|
+
return svgObjects;
|
|
1730
|
+
};
|
|
1731
|
+
|
|
1732
|
+
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component.ts
|
|
1733
|
+
function createSvgObjectsFromSchematicComponent(params) {
|
|
1734
|
+
const { component } = params;
|
|
1735
|
+
if (component.symbol_name) {
|
|
1736
|
+
return createSvgObjectsFromSchematicComponentWithSymbol(params);
|
|
1737
|
+
}
|
|
1738
|
+
return createSvgObjectsFromSchematicComponentWithBox(params);
|
|
1534
1739
|
}
|
|
1535
1740
|
|
|
1536
1741
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-debug-object.ts
|
|
1537
|
-
import { applyToPoint as
|
|
1742
|
+
import { applyToPoint as applyToPoint21 } from "transformation-matrix";
|
|
1538
1743
|
function createSvgObjectsFromSchDebugObject(debugObject, transform) {
|
|
1539
1744
|
if (debugObject.shape === "rect") {
|
|
1540
|
-
let [screenLeft, screenTop] =
|
|
1745
|
+
let [screenLeft, screenTop] = applyToPoint21(transform, [
|
|
1541
1746
|
debugObject.center.x - debugObject.size.width / 2,
|
|
1542
1747
|
debugObject.center.y - debugObject.size.height / 2
|
|
1543
1748
|
]);
|
|
1544
|
-
let [screenRight, screenBottom] =
|
|
1749
|
+
let [screenRight, screenBottom] = applyToPoint21(transform, [
|
|
1545
1750
|
debugObject.center.x + debugObject.size.width / 2,
|
|
1546
1751
|
debugObject.center.y + debugObject.size.height / 2
|
|
1547
1752
|
]);
|
|
@@ -1551,7 +1756,7 @@ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
|
|
|
1551
1756
|
];
|
|
1552
1757
|
const width = Math.abs(screenRight - screenLeft);
|
|
1553
1758
|
const height = Math.abs(screenBottom - screenTop);
|
|
1554
|
-
const [screenCenterX, screenCenterY] =
|
|
1759
|
+
const [screenCenterX, screenCenterY] = applyToPoint21(transform, [
|
|
1555
1760
|
debugObject.center.x,
|
|
1556
1761
|
debugObject.center.y
|
|
1557
1762
|
]);
|
|
@@ -1597,11 +1802,11 @@ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
|
|
|
1597
1802
|
];
|
|
1598
1803
|
}
|
|
1599
1804
|
if (debugObject.shape === "line") {
|
|
1600
|
-
const [screenStartX, screenStartY] =
|
|
1805
|
+
const [screenStartX, screenStartY] = applyToPoint21(transform, [
|
|
1601
1806
|
debugObject.start.x,
|
|
1602
1807
|
debugObject.start.y
|
|
1603
1808
|
]);
|
|
1604
|
-
const [screenEndX, screenEndY] =
|
|
1809
|
+
const [screenEndX, screenEndY] = applyToPoint21(transform, [
|
|
1605
1810
|
debugObject.end.x,
|
|
1606
1811
|
debugObject.end.y
|
|
1607
1812
|
]);
|
|
@@ -1651,7 +1856,7 @@ function createSvgObjectsFromSchDebugObject(debugObject, transform) {
|
|
|
1651
1856
|
}
|
|
1652
1857
|
|
|
1653
1858
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts
|
|
1654
|
-
import { applyToPoint as
|
|
1859
|
+
import { applyToPoint as applyToPoint22 } from "transformation-matrix";
|
|
1655
1860
|
function createSchematicTrace(trace, transform) {
|
|
1656
1861
|
const edges = trace.edges;
|
|
1657
1862
|
if (edges.length === 0) return [];
|
|
@@ -1665,11 +1870,11 @@ function createSchematicTrace(trace, transform) {
|
|
|
1665
1870
|
x: edge.to.x ?? edge.to.center?.x,
|
|
1666
1871
|
y: edge.to.y ?? edge.to.center?.y
|
|
1667
1872
|
};
|
|
1668
|
-
const [transformedFromX, transformedFromY] =
|
|
1873
|
+
const [transformedFromX, transformedFromY] = applyToPoint22(transform, [
|
|
1669
1874
|
fromPoint.x,
|
|
1670
1875
|
fromPoint.y
|
|
1671
1876
|
]);
|
|
1672
|
-
const [transformedToX, transformedToY] =
|
|
1877
|
+
const [transformedToX, transformedToY] = applyToPoint22(transform, [
|
|
1673
1878
|
toPoint.x,
|
|
1674
1879
|
toPoint.y
|
|
1675
1880
|
]);
|
|
@@ -1686,8 +1891,9 @@ function createSchematicTrace(trace, transform) {
|
|
|
1686
1891
|
attributes: {
|
|
1687
1892
|
class: "trace",
|
|
1688
1893
|
d: path,
|
|
1689
|
-
|
|
1690
|
-
|
|
1894
|
+
stroke: colorMap.schematic.wire,
|
|
1895
|
+
fill: "none",
|
|
1896
|
+
"stroke-width": `${getSchStrokeSize(transform)}px`
|
|
1691
1897
|
},
|
|
1692
1898
|
value: "",
|
|
1693
1899
|
children: []
|
|
@@ -1697,24 +1903,38 @@ function createSchematicTrace(trace, transform) {
|
|
|
1697
1903
|
|
|
1698
1904
|
// lib/sch/convert-circuit-json-to-schematic-svg.ts
|
|
1699
1905
|
function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
1700
|
-
const
|
|
1701
|
-
const
|
|
1702
|
-
const
|
|
1703
|
-
const circuitWidth = maxX - minX + 2 * padding;
|
|
1704
|
-
const circuitHeight = maxY - minY + 2 * padding;
|
|
1906
|
+
const realBounds = getSchematicBoundsFromCircuitJson(circuitJson);
|
|
1907
|
+
const realWidth = realBounds.maxX - realBounds.minX;
|
|
1908
|
+
const realHeight = realBounds.maxY - realBounds.minY;
|
|
1705
1909
|
const svgWidth = options?.width ?? 1200;
|
|
1706
1910
|
const svgHeight = options?.height ?? 600;
|
|
1707
|
-
const
|
|
1708
|
-
const
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1911
|
+
const circuitAspectRatio = realWidth / realHeight;
|
|
1912
|
+
const containerAspectRatio = svgWidth / svgHeight;
|
|
1913
|
+
let screenPaddingPx;
|
|
1914
|
+
if (circuitAspectRatio > containerAspectRatio) {
|
|
1915
|
+
const newHeight = svgWidth / circuitAspectRatio;
|
|
1916
|
+
screenPaddingPx = {
|
|
1917
|
+
x: 0,
|
|
1918
|
+
y: (svgHeight - newHeight) / 2
|
|
1919
|
+
};
|
|
1920
|
+
} else {
|
|
1921
|
+
const newWidth = svgHeight * circuitAspectRatio;
|
|
1922
|
+
screenPaddingPx = {
|
|
1923
|
+
x: (svgWidth - newWidth) / 2,
|
|
1924
|
+
y: 0
|
|
1925
|
+
};
|
|
1926
|
+
}
|
|
1927
|
+
const transform = fromTriangles(
|
|
1928
|
+
[
|
|
1929
|
+
{ x: realBounds.minX, y: realBounds.maxY },
|
|
1930
|
+
{ x: realBounds.maxX, y: realBounds.maxY },
|
|
1931
|
+
{ x: realBounds.maxX, y: realBounds.minY }
|
|
1932
|
+
],
|
|
1933
|
+
[
|
|
1934
|
+
{ x: screenPaddingPx.x, y: screenPaddingPx.y },
|
|
1935
|
+
{ x: svgWidth - screenPaddingPx.x, y: screenPaddingPx.y },
|
|
1936
|
+
{ x: svgWidth - screenPaddingPx.x, y: svgHeight - screenPaddingPx.y }
|
|
1937
|
+
]
|
|
1718
1938
|
);
|
|
1719
1939
|
const svgChildren = [];
|
|
1720
1940
|
svgChildren.push({
|
|
@@ -1732,7 +1952,9 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
|
1732
1952
|
});
|
|
1733
1953
|
if (options?.grid) {
|
|
1734
1954
|
const gridConfig = typeof options.grid === "object" ? options.grid : {};
|
|
1735
|
-
svgChildren.push(
|
|
1955
|
+
svgChildren.push(
|
|
1956
|
+
drawSchematicGrid({ bounds: realBounds, transform, ...gridConfig })
|
|
1957
|
+
);
|
|
1736
1958
|
}
|
|
1737
1959
|
if (options?.labeledPoints) {
|
|
1738
1960
|
svgChildren.push(
|
|
@@ -1752,7 +1974,7 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
|
1752
1974
|
);
|
|
1753
1975
|
} else if (elm.type === "schematic_component") {
|
|
1754
1976
|
schComponentSvgs.push(
|
|
1755
|
-
...
|
|
1977
|
+
...createSvgObjectsFromSchematicComponent({
|
|
1756
1978
|
component: elm,
|
|
1757
1979
|
transform,
|
|
1758
1980
|
circuitJson
|
|
@@ -1780,17 +2002,19 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
|
1780
2002
|
children: [
|
|
1781
2003
|
{
|
|
1782
2004
|
type: "text",
|
|
2005
|
+
// DO NOT USE THESE CLASSES!!!!
|
|
2006
|
+
// PUT STYLES IN THE SVG OBJECTS THEMSELVES
|
|
1783
2007
|
value: `
|
|
1784
2008
|
.boundary { fill: ${colorMap.schematic.background}; }
|
|
1785
|
-
.schematic-boundary { fill: none; stroke: #fff;
|
|
2009
|
+
.schematic-boundary { fill: none; stroke: #fff; }
|
|
1786
2010
|
.component { fill: none; stroke: ${colorMap.schematic.component_outline}; }
|
|
1787
2011
|
.chip { fill: ${colorMap.schematic.component_body}; stroke: ${colorMap.schematic.component_outline}; }
|
|
1788
2012
|
.component-pin { fill: none; stroke: ${colorMap.schematic.component_outline}; }
|
|
1789
|
-
.trace { stroke: ${colorMap.schematic.wire};
|
|
1790
|
-
.text { font-family:
|
|
1791
|
-
.pin-number {
|
|
2013
|
+
.trace { stroke: ${colorMap.schematic.wire}; }
|
|
2014
|
+
.text { font-family: sans-serif; fill: ${colorMap.schematic.wire}; }
|
|
2015
|
+
.pin-number { fill: ${colorMap.schematic.pin_number}; }
|
|
1792
2016
|
.port-label { fill: ${colorMap.schematic.reference}; }
|
|
1793
|
-
.component-name {
|
|
2017
|
+
.component-name { fill: ${colorMap.schematic.reference}; }
|
|
1794
2018
|
`,
|
|
1795
2019
|
name: "",
|
|
1796
2020
|
attributes: {},
|