circuit-to-svg 0.0.121 → 0.0.123
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 +238 -63
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -18,7 +18,62 @@ function createSvgObjectsFromPcbTraceError(pcbTraceError, transform, circuitJson
|
|
|
18
18
|
const port2 = circuitJson.find(
|
|
19
19
|
(el) => el.type === "pcb_port" && el.pcb_port_id === pcb_port_ids?.[1]
|
|
20
20
|
);
|
|
21
|
-
if (!port1 || !port2)
|
|
21
|
+
if (!port1 || !port2) {
|
|
22
|
+
const viaIdMatch = pcbTraceError.message?.match(
|
|
23
|
+
/pcb_via\[#?(pcb_via_\d+)\]/
|
|
24
|
+
);
|
|
25
|
+
const viaId = viaIdMatch?.[1];
|
|
26
|
+
const via = circuitJson.find(
|
|
27
|
+
(el) => el.type === "pcb_via" && el.pcb_via_id === viaId
|
|
28
|
+
);
|
|
29
|
+
if (via && via.type === "pcb_via") {
|
|
30
|
+
return createSvgObjectsForViaTraceError(pcbTraceError, via, transform);
|
|
31
|
+
}
|
|
32
|
+
if (pcbTraceError.center) {
|
|
33
|
+
const screenCenter = applyToPoint(transform, {
|
|
34
|
+
x: pcbTraceError.center.x,
|
|
35
|
+
y: pcbTraceError.center.y
|
|
36
|
+
});
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
name: "rect",
|
|
40
|
+
type: "element",
|
|
41
|
+
attributes: {
|
|
42
|
+
x: (screenCenter.x - 5).toString(),
|
|
43
|
+
y: (screenCenter.y - 5).toString(),
|
|
44
|
+
width: "10",
|
|
45
|
+
height: "10",
|
|
46
|
+
fill: "red",
|
|
47
|
+
transform: `rotate(45 ${screenCenter.x} ${screenCenter.y})`
|
|
48
|
+
},
|
|
49
|
+
children: [],
|
|
50
|
+
value: ""
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "text",
|
|
54
|
+
type: "element",
|
|
55
|
+
attributes: {
|
|
56
|
+
x: screenCenter.x.toString(),
|
|
57
|
+
y: (screenCenter.y - 15).toString(),
|
|
58
|
+
fill: "red",
|
|
59
|
+
"font-family": "sans-serif",
|
|
60
|
+
"font-size": "12",
|
|
61
|
+
"text-anchor": "middle"
|
|
62
|
+
},
|
|
63
|
+
children: [
|
|
64
|
+
{
|
|
65
|
+
type: "text",
|
|
66
|
+
value: pcbTraceError.message || "Pcb Trace Error",
|
|
67
|
+
name: "",
|
|
68
|
+
attributes: {},
|
|
69
|
+
children: []
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
value: ""
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
} else return [];
|
|
76
|
+
}
|
|
22
77
|
const screenPort1 = applyToPoint(transform, {
|
|
23
78
|
x: port1.x,
|
|
24
79
|
y: port1.y
|
|
@@ -104,6 +159,86 @@ function createSvgObjectsFromPcbTraceError(pcbTraceError, transform, circuitJson
|
|
|
104
159
|
];
|
|
105
160
|
return svgObjects;
|
|
106
161
|
}
|
|
162
|
+
function createSvgObjectsForViaTraceError(pcbTraceError, via, transform) {
|
|
163
|
+
if (pcbTraceError.center && via) {
|
|
164
|
+
const screenCenter = applyToPoint(transform, {
|
|
165
|
+
x: pcbTraceError.center.x,
|
|
166
|
+
y: pcbTraceError.center.y
|
|
167
|
+
});
|
|
168
|
+
const screenVia = applyToPoint(transform, {
|
|
169
|
+
x: via.x,
|
|
170
|
+
y: via.y
|
|
171
|
+
});
|
|
172
|
+
const dx = screenVia.x - screenCenter.x;
|
|
173
|
+
const dy = screenVia.y - screenCenter.y;
|
|
174
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
175
|
+
const angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
176
|
+
const margin = 10;
|
|
177
|
+
const boxWidth = dist + margin * 2;
|
|
178
|
+
const boxHeight = 20;
|
|
179
|
+
const midX = (screenCenter.x + screenVia.x) / 2;
|
|
180
|
+
const midY = (screenCenter.y + screenVia.y) / 2;
|
|
181
|
+
return [
|
|
182
|
+
// Rotated bounding box
|
|
183
|
+
{
|
|
184
|
+
name: "rect",
|
|
185
|
+
type: "element",
|
|
186
|
+
attributes: {
|
|
187
|
+
x: (midX - boxWidth / 2).toString(),
|
|
188
|
+
y: (midY - boxHeight / 2).toString(),
|
|
189
|
+
width: boxWidth.toString(),
|
|
190
|
+
height: boxHeight.toString(),
|
|
191
|
+
fill: "none",
|
|
192
|
+
stroke: "red",
|
|
193
|
+
"stroke-width": "1",
|
|
194
|
+
"stroke-dasharray": "3,2",
|
|
195
|
+
transform: `rotate(${angle} ${midX} ${midY})`
|
|
196
|
+
},
|
|
197
|
+
children: [],
|
|
198
|
+
value: ""
|
|
199
|
+
},
|
|
200
|
+
// Error diamond
|
|
201
|
+
{
|
|
202
|
+
name: "rect",
|
|
203
|
+
type: "element",
|
|
204
|
+
attributes: {
|
|
205
|
+
x: (midX - 5).toString(),
|
|
206
|
+
y: (midY - 5).toString(),
|
|
207
|
+
width: "10",
|
|
208
|
+
height: "10",
|
|
209
|
+
fill: "red",
|
|
210
|
+
transform: `rotate(45 ${midX} ${midY})`
|
|
211
|
+
},
|
|
212
|
+
children: [],
|
|
213
|
+
value: ""
|
|
214
|
+
},
|
|
215
|
+
// Error label
|
|
216
|
+
{
|
|
217
|
+
name: "text",
|
|
218
|
+
type: "element",
|
|
219
|
+
attributes: {
|
|
220
|
+
x: midX.toString(),
|
|
221
|
+
y: (midY - boxHeight / 2 - 5).toString(),
|
|
222
|
+
fill: "red",
|
|
223
|
+
"font-family": "sans-serif",
|
|
224
|
+
"font-size": "12",
|
|
225
|
+
"text-anchor": "middle"
|
|
226
|
+
},
|
|
227
|
+
children: [
|
|
228
|
+
{
|
|
229
|
+
type: "text",
|
|
230
|
+
value: pcbTraceError.message || "Pcb Trace Error",
|
|
231
|
+
name: "",
|
|
232
|
+
attributes: {},
|
|
233
|
+
children: []
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
value: ""
|
|
237
|
+
}
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
107
242
|
|
|
108
243
|
// lib/pcb/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts
|
|
109
244
|
import { applyToPoint as applyToPoint2 } from "transformation-matrix";
|
|
@@ -1351,12 +1486,35 @@ var getSchScreenFontSize = (transform, textType) => {
|
|
|
1351
1486
|
};
|
|
1352
1487
|
|
|
1353
1488
|
// lib/assembly/svg-object-fns/create-svg-objects-from-assembly-component.ts
|
|
1354
|
-
function createSvgObjectsFromAssemblyComponent(
|
|
1355
|
-
const {
|
|
1489
|
+
function createSvgObjectsFromAssemblyComponent(params, ctx) {
|
|
1490
|
+
const { elm, portPosition, name, arePinsInterchangeable } = params;
|
|
1491
|
+
const { transform } = ctx;
|
|
1492
|
+
const { center, width, height, rotation = 0, layer = "top" } = elm;
|
|
1493
|
+
if (!center || typeof width !== "number" || typeof height !== "number")
|
|
1494
|
+
return null;
|
|
1356
1495
|
const [x, y] = applyToPoint19(transform, [center.x, center.y]);
|
|
1357
|
-
const [pinX, pinY] = applyToPoint19(transform, [
|
|
1496
|
+
const [pinX, pinY] = applyToPoint19(transform, [portPosition.x, portPosition.y]);
|
|
1358
1497
|
const scaledWidth = width * Math.abs(transform.a);
|
|
1359
1498
|
const scaledHeight = height * Math.abs(transform.d);
|
|
1499
|
+
const isTopLayer = layer === "top";
|
|
1500
|
+
const isPinTop = pinY > y;
|
|
1501
|
+
const isPinLeft = pinX < x;
|
|
1502
|
+
const children = [
|
|
1503
|
+
createComponentPath(scaledWidth, scaledHeight, rotation, layer),
|
|
1504
|
+
createComponentLabel(scaledWidth, scaledHeight, name ?? "", transform)
|
|
1505
|
+
];
|
|
1506
|
+
if (!arePinsInterchangeable) {
|
|
1507
|
+
children.push(
|
|
1508
|
+
createPin1Indicator(
|
|
1509
|
+
scaledWidth,
|
|
1510
|
+
scaledHeight,
|
|
1511
|
+
rotation,
|
|
1512
|
+
layer,
|
|
1513
|
+
isPinTop,
|
|
1514
|
+
isPinLeft
|
|
1515
|
+
)
|
|
1516
|
+
);
|
|
1517
|
+
}
|
|
1360
1518
|
return {
|
|
1361
1519
|
name: "g",
|
|
1362
1520
|
type: "element",
|
|
@@ -1364,29 +1522,14 @@ function createSvgObjectsFromAssemblyComponent(component, transform, firstPin, n
|
|
|
1364
1522
|
attributes: {
|
|
1365
1523
|
transform: `translate(${x}, ${y}) scale(1, -1)`
|
|
1366
1524
|
},
|
|
1367
|
-
children
|
|
1368
|
-
createComponentPath(
|
|
1369
|
-
scaledWidth,
|
|
1370
|
-
scaledHeight,
|
|
1371
|
-
x,
|
|
1372
|
-
y,
|
|
1373
|
-
pinX,
|
|
1374
|
-
pinY,
|
|
1375
|
-
rotation,
|
|
1376
|
-
layer
|
|
1377
|
-
),
|
|
1378
|
-
createComponentLabel(scaledWidth, scaledHeight, name ?? "", transform)
|
|
1379
|
-
]
|
|
1525
|
+
children
|
|
1380
1526
|
};
|
|
1381
1527
|
}
|
|
1382
|
-
function createComponentPath(scaledWidth, scaledHeight,
|
|
1528
|
+
function createComponentPath(scaledWidth, scaledHeight, rotation, layer) {
|
|
1383
1529
|
const w = scaledWidth / 2;
|
|
1384
1530
|
const h = scaledHeight / 2;
|
|
1385
|
-
const cornerSize = Math.min(w, h) * 0.3;
|
|
1386
|
-
const isTop = pinY > centerY;
|
|
1387
|
-
const isLeft = pinX < centerX;
|
|
1388
1531
|
const strokeWidth = 0.8;
|
|
1389
|
-
const path =
|
|
1532
|
+
const path = getRectPathData(w, h, rotation);
|
|
1390
1533
|
return {
|
|
1391
1534
|
name: "path",
|
|
1392
1535
|
type: "element",
|
|
@@ -1436,47 +1579,76 @@ function createComponentLabel(scaledWidth, scaledHeight, name, transform) {
|
|
|
1436
1579
|
value: ""
|
|
1437
1580
|
};
|
|
1438
1581
|
}
|
|
1439
|
-
function
|
|
1440
|
-
const
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
let corners;
|
|
1447
|
-
if (isTop && isLeft) {
|
|
1448
|
-
corners = [
|
|
1449
|
-
[-w, -h + cornerSize],
|
|
1450
|
-
[-w + cornerSize, -h],
|
|
1451
|
-
[w, -h],
|
|
1452
|
-
[w, h],
|
|
1453
|
-
[-w, h]
|
|
1454
|
-
];
|
|
1455
|
-
} else if (isTop && !isLeft) {
|
|
1456
|
-
corners = [
|
|
1582
|
+
function createPin1Indicator(scaledWidth, scaledHeight, rotation, layer, isPinTop, isPinLeft) {
|
|
1583
|
+
const w = scaledWidth / 2;
|
|
1584
|
+
const h = scaledHeight / 2;
|
|
1585
|
+
const indicatorSize = Math.min(w, h) * 0.5;
|
|
1586
|
+
let points;
|
|
1587
|
+
if (isPinTop && isPinLeft) {
|
|
1588
|
+
points = [
|
|
1457
1589
|
[-w, -h],
|
|
1458
|
-
|
|
1459
|
-
[w, -h
|
|
1460
|
-
|
|
1461
|
-
[-w, h]
|
|
1590
|
+
// Corner point
|
|
1591
|
+
[-w + indicatorSize, -h],
|
|
1592
|
+
// Point along top edge
|
|
1593
|
+
[-w, -h + indicatorSize]
|
|
1594
|
+
// Point along left edge
|
|
1462
1595
|
];
|
|
1463
|
-
} else if (
|
|
1464
|
-
|
|
1465
|
-
[-w, -h],
|
|
1596
|
+
} else if (isPinTop && !isPinLeft) {
|
|
1597
|
+
points = [
|
|
1466
1598
|
[w, -h],
|
|
1467
|
-
|
|
1468
|
-
[
|
|
1469
|
-
|
|
1599
|
+
// Corner point
|
|
1600
|
+
[w - indicatorSize, -h],
|
|
1601
|
+
// Point along top edge
|
|
1602
|
+
[w, -h + indicatorSize]
|
|
1603
|
+
// Point along right edge
|
|
1604
|
+
];
|
|
1605
|
+
} else if (!isPinTop && isPinLeft) {
|
|
1606
|
+
points = [
|
|
1607
|
+
[-w, h],
|
|
1608
|
+
// Corner point
|
|
1609
|
+
[-w + indicatorSize, h],
|
|
1610
|
+
// Point along bottom edge
|
|
1611
|
+
[-w, h - indicatorSize]
|
|
1612
|
+
// Point along left edge
|
|
1470
1613
|
];
|
|
1471
1614
|
} else {
|
|
1472
|
-
|
|
1473
|
-
[
|
|
1474
|
-
|
|
1475
|
-
[w, h
|
|
1476
|
-
|
|
1477
|
-
[
|
|
1615
|
+
points = [
|
|
1616
|
+
[w, h],
|
|
1617
|
+
// Corner point
|
|
1618
|
+
[w - indicatorSize, h],
|
|
1619
|
+
// Point along bottom edge
|
|
1620
|
+
[w, h - indicatorSize]
|
|
1621
|
+
// Point along right edge
|
|
1478
1622
|
];
|
|
1479
1623
|
}
|
|
1624
|
+
const pointsString = points.map((p) => p.join(",")).join(" ");
|
|
1625
|
+
return {
|
|
1626
|
+
name: "polygon",
|
|
1627
|
+
type: "element",
|
|
1628
|
+
attributes: {
|
|
1629
|
+
class: "assembly-pin1-indicator",
|
|
1630
|
+
points: pointsString,
|
|
1631
|
+
fill: "#333",
|
|
1632
|
+
stroke: "none",
|
|
1633
|
+
transform: `rotate(${-rotation})`
|
|
1634
|
+
},
|
|
1635
|
+
value: "",
|
|
1636
|
+
children: []
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
function getRectPathData(w, h, rotation) {
|
|
1640
|
+
const rotatePoint = (x, y, angle) => {
|
|
1641
|
+
const rad = Math.PI / 180 * angle;
|
|
1642
|
+
const cos = Math.cos(rad);
|
|
1643
|
+
const sin = Math.sin(rad);
|
|
1644
|
+
return [x * cos - y * sin, x * sin + y * cos];
|
|
1645
|
+
};
|
|
1646
|
+
const corners = [
|
|
1647
|
+
[-w, -h],
|
|
1648
|
+
[w, -h],
|
|
1649
|
+
[w, h],
|
|
1650
|
+
[-w, h]
|
|
1651
|
+
];
|
|
1480
1652
|
const rotatedCorners = corners.map(([x, y]) => rotatePoint(x, y, rotation));
|
|
1481
1653
|
const path = rotatedCorners.map(([x, y], i) => i === 0 ? `M${x},${y}` : `L${x},${y}`).join(" ");
|
|
1482
1654
|
return `${path} Z`;
|
|
@@ -1599,14 +1771,17 @@ function createSvgObjects2(elm, transform, soup) {
|
|
|
1599
1771
|
const ports = su3(soup).pcb_port.list().filter((port) => port.pcb_component_id === elm.pcb_component_id);
|
|
1600
1772
|
const firstPort = ports[0];
|
|
1601
1773
|
if (sourceComponent && firstPort) {
|
|
1602
|
-
|
|
1603
|
-
|
|
1774
|
+
const arePinsInterchangeable = sourceComponent.are_pins_interchangeable;
|
|
1775
|
+
const obj = createSvgObjectsFromAssemblyComponent(
|
|
1776
|
+
{
|
|
1604
1777
|
elm,
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1778
|
+
portPosition: { x: firstPort.x, y: firstPort.y },
|
|
1779
|
+
name: sourceComponent.name,
|
|
1780
|
+
arePinsInterchangeable
|
|
1781
|
+
},
|
|
1782
|
+
{ transform }
|
|
1783
|
+
);
|
|
1784
|
+
return obj ? [obj] : [];
|
|
1610
1785
|
}
|
|
1611
1786
|
return [];
|
|
1612
1787
|
}
|