@tscircuit/cli 0.1.1480 → 0.1.1482
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/cli/main.js +937 -226
- package/dist/lib/index.js +783 -72
- package/package.json +2 -2
package/dist/lib/index.js
CHANGED
|
@@ -65808,7 +65808,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
|
|
|
65808
65808
|
}));
|
|
65809
65809
|
};
|
|
65810
65810
|
// package.json
|
|
65811
|
-
var version = "0.1.
|
|
65811
|
+
var version = "0.1.1481";
|
|
65812
65812
|
var package_default = {
|
|
65813
65813
|
name: "@tscircuit/cli",
|
|
65814
65814
|
version,
|
|
@@ -65846,7 +65846,7 @@ var package_default = {
|
|
|
65846
65846
|
"circuit-json": "^0.0.425",
|
|
65847
65847
|
"circuit-json-to-bom-csv": "^0.0.7",
|
|
65848
65848
|
"circuit-json-to-gerber": "^0.0.51",
|
|
65849
|
-
"circuit-json-to-kicad": "0.0.
|
|
65849
|
+
"circuit-json-to-kicad": "0.0.150",
|
|
65850
65850
|
"circuit-json-to-pnp-csv": "^0.0.7",
|
|
65851
65851
|
"circuit-json-to-readable-netlist": "^0.0.15",
|
|
65852
65852
|
"circuit-json-to-spice": "^0.0.10",
|
|
@@ -68485,12 +68485,466 @@ import {
|
|
|
68485
68485
|
import { KicadPcb as KicadPcb2 } from "kicadts";
|
|
68486
68486
|
import { cju as cju2 } from "@tscircuit/circuit-json-util";
|
|
68487
68487
|
import { compose as compose6, translate as translate6, scale as scale4 } from "transformation-matrix";
|
|
68488
|
+
|
|
68489
|
+
// node_modules/earcut/src/earcut.js
|
|
68490
|
+
function earcut(data, holeIndices, dim = 2) {
|
|
68491
|
+
const hasHoles = holeIndices && holeIndices.length;
|
|
68492
|
+
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
|
|
68493
|
+
let outerNode = linkedList(data, 0, outerLen, dim, true);
|
|
68494
|
+
const triangles = [];
|
|
68495
|
+
if (!outerNode || outerNode.next === outerNode.prev)
|
|
68496
|
+
return triangles;
|
|
68497
|
+
let minX, minY, invSize;
|
|
68498
|
+
if (hasHoles)
|
|
68499
|
+
outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
|
|
68500
|
+
if (data.length > 80 * dim) {
|
|
68501
|
+
minX = data[0];
|
|
68502
|
+
minY = data[1];
|
|
68503
|
+
let maxX = minX;
|
|
68504
|
+
let maxY = minY;
|
|
68505
|
+
for (let i = dim;i < outerLen; i += dim) {
|
|
68506
|
+
const x = data[i];
|
|
68507
|
+
const y = data[i + 1];
|
|
68508
|
+
if (x < minX)
|
|
68509
|
+
minX = x;
|
|
68510
|
+
if (y < minY)
|
|
68511
|
+
minY = y;
|
|
68512
|
+
if (x > maxX)
|
|
68513
|
+
maxX = x;
|
|
68514
|
+
if (y > maxY)
|
|
68515
|
+
maxY = y;
|
|
68516
|
+
}
|
|
68517
|
+
invSize = Math.max(maxX - minX, maxY - minY);
|
|
68518
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
|
68519
|
+
}
|
|
68520
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
|
68521
|
+
return triangles;
|
|
68522
|
+
}
|
|
68523
|
+
function linkedList(data, start, end, dim, clockwise) {
|
|
68524
|
+
let last;
|
|
68525
|
+
if (clockwise === signedArea(data, start, end, dim) > 0) {
|
|
68526
|
+
for (let i = start;i < end; i += dim)
|
|
68527
|
+
last = insertNode(i / dim | 0, data[i], data[i + 1], last);
|
|
68528
|
+
} else {
|
|
68529
|
+
for (let i = end - dim;i >= start; i -= dim)
|
|
68530
|
+
last = insertNode(i / dim | 0, data[i], data[i + 1], last);
|
|
68531
|
+
}
|
|
68532
|
+
if (last && equals(last, last.next)) {
|
|
68533
|
+
removeNode(last);
|
|
68534
|
+
last = last.next;
|
|
68535
|
+
}
|
|
68536
|
+
return last;
|
|
68537
|
+
}
|
|
68538
|
+
function filterPoints(start, end) {
|
|
68539
|
+
if (!start)
|
|
68540
|
+
return start;
|
|
68541
|
+
if (!end)
|
|
68542
|
+
end = start;
|
|
68543
|
+
let p = start, again;
|
|
68544
|
+
do {
|
|
68545
|
+
again = false;
|
|
68546
|
+
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
|
|
68547
|
+
removeNode(p);
|
|
68548
|
+
p = end = p.prev;
|
|
68549
|
+
if (p === p.next)
|
|
68550
|
+
break;
|
|
68551
|
+
again = true;
|
|
68552
|
+
} else {
|
|
68553
|
+
p = p.next;
|
|
68554
|
+
}
|
|
68555
|
+
} while (again || p !== end);
|
|
68556
|
+
return end;
|
|
68557
|
+
}
|
|
68558
|
+
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
68559
|
+
if (!ear)
|
|
68560
|
+
return;
|
|
68561
|
+
if (!pass && invSize)
|
|
68562
|
+
indexCurve(ear, minX, minY, invSize);
|
|
68563
|
+
let stop = ear;
|
|
68564
|
+
while (ear.prev !== ear.next) {
|
|
68565
|
+
const prev = ear.prev;
|
|
68566
|
+
const next = ear.next;
|
|
68567
|
+
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
68568
|
+
triangles.push(prev.i, ear.i, next.i);
|
|
68569
|
+
removeNode(ear);
|
|
68570
|
+
ear = next.next;
|
|
68571
|
+
stop = next.next;
|
|
68572
|
+
continue;
|
|
68573
|
+
}
|
|
68574
|
+
ear = next;
|
|
68575
|
+
if (ear === stop) {
|
|
68576
|
+
if (!pass) {
|
|
68577
|
+
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
68578
|
+
} else if (pass === 1) {
|
|
68579
|
+
ear = cureLocalIntersections(filterPoints(ear), triangles);
|
|
68580
|
+
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
68581
|
+
} else if (pass === 2) {
|
|
68582
|
+
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
68583
|
+
}
|
|
68584
|
+
break;
|
|
68585
|
+
}
|
|
68586
|
+
}
|
|
68587
|
+
}
|
|
68588
|
+
function isEar(ear) {
|
|
68589
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
68590
|
+
if (area(a, b, c) >= 0)
|
|
68591
|
+
return false;
|
|
68592
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
68593
|
+
const x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy);
|
|
68594
|
+
let p = c.next;
|
|
68595
|
+
while (p !== a) {
|
|
68596
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
68597
|
+
return false;
|
|
68598
|
+
p = p.next;
|
|
68599
|
+
}
|
|
68600
|
+
return true;
|
|
68601
|
+
}
|
|
68602
|
+
function isEarHashed(ear, minX, minY, invSize) {
|
|
68603
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
68604
|
+
if (area(a, b, c) >= 0)
|
|
68605
|
+
return false;
|
|
68606
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
68607
|
+
const x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy);
|
|
68608
|
+
const minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
|
|
68609
|
+
let { prevZ: p, nextZ: n } = ear;
|
|
68610
|
+
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
|
68611
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
68612
|
+
return false;
|
|
68613
|
+
p = p.prevZ;
|
|
68614
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
68615
|
+
return false;
|
|
68616
|
+
n = n.nextZ;
|
|
68617
|
+
}
|
|
68618
|
+
while (p && p.z >= minZ) {
|
|
68619
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0)
|
|
68620
|
+
return false;
|
|
68621
|
+
p = p.prevZ;
|
|
68622
|
+
}
|
|
68623
|
+
while (n && n.z <= maxZ) {
|
|
68624
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
68625
|
+
return false;
|
|
68626
|
+
n = n.nextZ;
|
|
68627
|
+
}
|
|
68628
|
+
return true;
|
|
68629
|
+
}
|
|
68630
|
+
function cureLocalIntersections(start, triangles) {
|
|
68631
|
+
let p = start;
|
|
68632
|
+
do {
|
|
68633
|
+
const a = p.prev, b = p.next.next;
|
|
68634
|
+
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
68635
|
+
triangles.push(a.i, p.i, b.i);
|
|
68636
|
+
removeNode(p);
|
|
68637
|
+
removeNode(p.next);
|
|
68638
|
+
p = start = b;
|
|
68639
|
+
}
|
|
68640
|
+
p = p.next;
|
|
68641
|
+
} while (p !== start);
|
|
68642
|
+
return filterPoints(p);
|
|
68643
|
+
}
|
|
68644
|
+
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
68645
|
+
let a = start;
|
|
68646
|
+
do {
|
|
68647
|
+
let b = a.next.next;
|
|
68648
|
+
while (b !== a.prev) {
|
|
68649
|
+
if (a.i !== b.i && isValidDiagonal(a, b)) {
|
|
68650
|
+
let c = splitPolygon(a, b);
|
|
68651
|
+
a = filterPoints(a, a.next);
|
|
68652
|
+
c = filterPoints(c, c.next);
|
|
68653
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
|
68654
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
|
68655
|
+
return;
|
|
68656
|
+
}
|
|
68657
|
+
b = b.next;
|
|
68658
|
+
}
|
|
68659
|
+
a = a.next;
|
|
68660
|
+
} while (a !== start);
|
|
68661
|
+
}
|
|
68662
|
+
function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
68663
|
+
const queue = [];
|
|
68664
|
+
for (let i = 0, len = holeIndices.length;i < len; i++) {
|
|
68665
|
+
const start = holeIndices[i] * dim;
|
|
68666
|
+
const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
68667
|
+
const list = linkedList(data, start, end, dim, false);
|
|
68668
|
+
if (list === list.next)
|
|
68669
|
+
list.steiner = true;
|
|
68670
|
+
queue.push(getLeftmost(list));
|
|
68671
|
+
}
|
|
68672
|
+
queue.sort(compareXYSlope);
|
|
68673
|
+
for (let i = 0;i < queue.length; i++) {
|
|
68674
|
+
outerNode = eliminateHole(queue[i], outerNode);
|
|
68675
|
+
}
|
|
68676
|
+
return outerNode;
|
|
68677
|
+
}
|
|
68678
|
+
function compareXYSlope(a, b) {
|
|
68679
|
+
let result = a.x - b.x;
|
|
68680
|
+
if (result === 0) {
|
|
68681
|
+
result = a.y - b.y;
|
|
68682
|
+
if (result === 0) {
|
|
68683
|
+
const aSlope = (a.next.y - a.y) / (a.next.x - a.x);
|
|
68684
|
+
const bSlope = (b.next.y - b.y) / (b.next.x - b.x);
|
|
68685
|
+
result = aSlope - bSlope;
|
|
68686
|
+
}
|
|
68687
|
+
}
|
|
68688
|
+
return result;
|
|
68689
|
+
}
|
|
68690
|
+
function eliminateHole(hole, outerNode) {
|
|
68691
|
+
const bridge = findHoleBridge(hole, outerNode);
|
|
68692
|
+
if (!bridge) {
|
|
68693
|
+
return outerNode;
|
|
68694
|
+
}
|
|
68695
|
+
const bridgeReverse = splitPolygon(bridge, hole);
|
|
68696
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
|
68697
|
+
return filterPoints(bridge, bridge.next);
|
|
68698
|
+
}
|
|
68699
|
+
function findHoleBridge(hole, outerNode) {
|
|
68700
|
+
let p = outerNode;
|
|
68701
|
+
const hx = hole.x;
|
|
68702
|
+
const hy = hole.y;
|
|
68703
|
+
let qx = -Infinity;
|
|
68704
|
+
let m;
|
|
68705
|
+
if (equals(hole, p))
|
|
68706
|
+
return p;
|
|
68707
|
+
do {
|
|
68708
|
+
if (equals(hole, p.next))
|
|
68709
|
+
return p.next;
|
|
68710
|
+
else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
|
|
68711
|
+
const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
|
|
68712
|
+
if (x <= hx && x > qx) {
|
|
68713
|
+
qx = x;
|
|
68714
|
+
m = p.x < p.next.x ? p : p.next;
|
|
68715
|
+
if (x === hx)
|
|
68716
|
+
return m;
|
|
68717
|
+
}
|
|
68718
|
+
}
|
|
68719
|
+
p = p.next;
|
|
68720
|
+
} while (p !== outerNode);
|
|
68721
|
+
if (!m)
|
|
68722
|
+
return null;
|
|
68723
|
+
const stop = m;
|
|
68724
|
+
const mx = m.x;
|
|
68725
|
+
const my = m.y;
|
|
68726
|
+
let tanMin = Infinity;
|
|
68727
|
+
p = m;
|
|
68728
|
+
do {
|
|
68729
|
+
if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
|
|
68730
|
+
const tan = Math.abs(hy - p.y) / (hx - p.x);
|
|
68731
|
+
if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
|
|
68732
|
+
m = p;
|
|
68733
|
+
tanMin = tan;
|
|
68734
|
+
}
|
|
68735
|
+
}
|
|
68736
|
+
p = p.next;
|
|
68737
|
+
} while (p !== stop);
|
|
68738
|
+
return m;
|
|
68739
|
+
}
|
|
68740
|
+
function sectorContainsSector(m, p) {
|
|
68741
|
+
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
|
|
68742
|
+
}
|
|
68743
|
+
function indexCurve(start, minX, minY, invSize) {
|
|
68744
|
+
let p = start;
|
|
68745
|
+
do {
|
|
68746
|
+
if (p.z === 0)
|
|
68747
|
+
p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
|
68748
|
+
p.prevZ = p.prev;
|
|
68749
|
+
p.nextZ = p.next;
|
|
68750
|
+
p = p.next;
|
|
68751
|
+
} while (p !== start);
|
|
68752
|
+
p.prevZ.nextZ = null;
|
|
68753
|
+
p.prevZ = null;
|
|
68754
|
+
sortLinked(p);
|
|
68755
|
+
}
|
|
68756
|
+
function sortLinked(list) {
|
|
68757
|
+
let numMerges;
|
|
68758
|
+
let inSize = 1;
|
|
68759
|
+
do {
|
|
68760
|
+
let p = list;
|
|
68761
|
+
let e;
|
|
68762
|
+
list = null;
|
|
68763
|
+
let tail = null;
|
|
68764
|
+
numMerges = 0;
|
|
68765
|
+
while (p) {
|
|
68766
|
+
numMerges++;
|
|
68767
|
+
let q = p;
|
|
68768
|
+
let pSize = 0;
|
|
68769
|
+
for (let i = 0;i < inSize; i++) {
|
|
68770
|
+
pSize++;
|
|
68771
|
+
q = q.nextZ;
|
|
68772
|
+
if (!q)
|
|
68773
|
+
break;
|
|
68774
|
+
}
|
|
68775
|
+
let qSize = inSize;
|
|
68776
|
+
while (pSize > 0 || qSize > 0 && q) {
|
|
68777
|
+
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
|
|
68778
|
+
e = p;
|
|
68779
|
+
p = p.nextZ;
|
|
68780
|
+
pSize--;
|
|
68781
|
+
} else {
|
|
68782
|
+
e = q;
|
|
68783
|
+
q = q.nextZ;
|
|
68784
|
+
qSize--;
|
|
68785
|
+
}
|
|
68786
|
+
if (tail)
|
|
68787
|
+
tail.nextZ = e;
|
|
68788
|
+
else
|
|
68789
|
+
list = e;
|
|
68790
|
+
e.prevZ = tail;
|
|
68791
|
+
tail = e;
|
|
68792
|
+
}
|
|
68793
|
+
p = q;
|
|
68794
|
+
}
|
|
68795
|
+
tail.nextZ = null;
|
|
68796
|
+
inSize *= 2;
|
|
68797
|
+
} while (numMerges > 1);
|
|
68798
|
+
return list;
|
|
68799
|
+
}
|
|
68800
|
+
function zOrder(x, y, minX, minY, invSize) {
|
|
68801
|
+
x = (x - minX) * invSize | 0;
|
|
68802
|
+
y = (y - minY) * invSize | 0;
|
|
68803
|
+
x = (x | x << 8) & 16711935;
|
|
68804
|
+
x = (x | x << 4) & 252645135;
|
|
68805
|
+
x = (x | x << 2) & 858993459;
|
|
68806
|
+
x = (x | x << 1) & 1431655765;
|
|
68807
|
+
y = (y | y << 8) & 16711935;
|
|
68808
|
+
y = (y | y << 4) & 252645135;
|
|
68809
|
+
y = (y | y << 2) & 858993459;
|
|
68810
|
+
y = (y | y << 1) & 1431655765;
|
|
68811
|
+
return x | y << 1;
|
|
68812
|
+
}
|
|
68813
|
+
function getLeftmost(start) {
|
|
68814
|
+
let p = start, leftmost = start;
|
|
68815
|
+
do {
|
|
68816
|
+
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y)
|
|
68817
|
+
leftmost = p;
|
|
68818
|
+
p = p.next;
|
|
68819
|
+
} while (p !== start);
|
|
68820
|
+
return leftmost;
|
|
68821
|
+
}
|
|
68822
|
+
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
68823
|
+
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
|
|
68824
|
+
}
|
|
68825
|
+
function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
|
|
68826
|
+
return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);
|
|
68827
|
+
}
|
|
68828
|
+
function isValidDiagonal(a, b) {
|
|
68829
|
+
return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && (area(a.prev, a, b.prev) || area(a, b.prev, b)) || equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
|
|
68830
|
+
}
|
|
68831
|
+
function area(p, q, r) {
|
|
68832
|
+
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
68833
|
+
}
|
|
68834
|
+
function equals(p1, p2) {
|
|
68835
|
+
return p1.x === p2.x && p1.y === p2.y;
|
|
68836
|
+
}
|
|
68837
|
+
function intersects(p1, q1, p2, q2) {
|
|
68838
|
+
const o1 = sign(area(p1, q1, p2));
|
|
68839
|
+
const o2 = sign(area(p1, q1, q2));
|
|
68840
|
+
const o3 = sign(area(p2, q2, p1));
|
|
68841
|
+
const o4 = sign(area(p2, q2, q1));
|
|
68842
|
+
if (o1 !== o2 && o3 !== o4)
|
|
68843
|
+
return true;
|
|
68844
|
+
if (o1 === 0 && onSegment(p1, p2, q1))
|
|
68845
|
+
return true;
|
|
68846
|
+
if (o2 === 0 && onSegment(p1, q2, q1))
|
|
68847
|
+
return true;
|
|
68848
|
+
if (o3 === 0 && onSegment(p2, p1, q2))
|
|
68849
|
+
return true;
|
|
68850
|
+
if (o4 === 0 && onSegment(p2, q1, q2))
|
|
68851
|
+
return true;
|
|
68852
|
+
return false;
|
|
68853
|
+
}
|
|
68854
|
+
function onSegment(p, q, r) {
|
|
68855
|
+
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
|
|
68856
|
+
}
|
|
68857
|
+
function sign(num) {
|
|
68858
|
+
return num > 0 ? 1 : num < 0 ? -1 : 0;
|
|
68859
|
+
}
|
|
68860
|
+
function intersectsPolygon(a, b) {
|
|
68861
|
+
let p = a;
|
|
68862
|
+
do {
|
|
68863
|
+
if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b))
|
|
68864
|
+
return true;
|
|
68865
|
+
p = p.next;
|
|
68866
|
+
} while (p !== a);
|
|
68867
|
+
return false;
|
|
68868
|
+
}
|
|
68869
|
+
function locallyInside(a, b) {
|
|
68870
|
+
return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
|
|
68871
|
+
}
|
|
68872
|
+
function middleInside(a, b) {
|
|
68873
|
+
let p = a;
|
|
68874
|
+
let inside = false;
|
|
68875
|
+
const px = (a.x + b.x) / 2;
|
|
68876
|
+
const py = (a.y + b.y) / 2;
|
|
68877
|
+
do {
|
|
68878
|
+
if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)
|
|
68879
|
+
inside = !inside;
|
|
68880
|
+
p = p.next;
|
|
68881
|
+
} while (p !== a);
|
|
68882
|
+
return inside;
|
|
68883
|
+
}
|
|
68884
|
+
function splitPolygon(a, b) {
|
|
68885
|
+
const a2 = createNode(a.i, a.x, a.y), b2 = createNode(b.i, b.x, b.y), an = a.next, bp = b.prev;
|
|
68886
|
+
a.next = b;
|
|
68887
|
+
b.prev = a;
|
|
68888
|
+
a2.next = an;
|
|
68889
|
+
an.prev = a2;
|
|
68890
|
+
b2.next = a2;
|
|
68891
|
+
a2.prev = b2;
|
|
68892
|
+
bp.next = b2;
|
|
68893
|
+
b2.prev = bp;
|
|
68894
|
+
return b2;
|
|
68895
|
+
}
|
|
68896
|
+
function insertNode(i, x, y, last) {
|
|
68897
|
+
const p = createNode(i, x, y);
|
|
68898
|
+
if (!last) {
|
|
68899
|
+
p.prev = p;
|
|
68900
|
+
p.next = p;
|
|
68901
|
+
} else {
|
|
68902
|
+
p.next = last.next;
|
|
68903
|
+
p.prev = last;
|
|
68904
|
+
last.next.prev = p;
|
|
68905
|
+
last.next = p;
|
|
68906
|
+
}
|
|
68907
|
+
return p;
|
|
68908
|
+
}
|
|
68909
|
+
function removeNode(p) {
|
|
68910
|
+
p.next.prev = p.prev;
|
|
68911
|
+
p.prev.next = p.next;
|
|
68912
|
+
if (p.prevZ)
|
|
68913
|
+
p.prevZ.nextZ = p.nextZ;
|
|
68914
|
+
if (p.nextZ)
|
|
68915
|
+
p.nextZ.prevZ = p.prevZ;
|
|
68916
|
+
}
|
|
68917
|
+
function createNode(i, x, y) {
|
|
68918
|
+
return {
|
|
68919
|
+
i,
|
|
68920
|
+
x,
|
|
68921
|
+
y,
|
|
68922
|
+
prev: null,
|
|
68923
|
+
next: null,
|
|
68924
|
+
z: 0,
|
|
68925
|
+
prevZ: null,
|
|
68926
|
+
nextZ: null,
|
|
68927
|
+
steiner: false
|
|
68928
|
+
};
|
|
68929
|
+
}
|
|
68930
|
+
function signedArea(data, start, end, dim) {
|
|
68931
|
+
let sum = 0;
|
|
68932
|
+
for (let i = start, j = end - dim;i < end; i += dim) {
|
|
68933
|
+
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
|
|
68934
|
+
j = i;
|
|
68935
|
+
}
|
|
68936
|
+
return sum;
|
|
68937
|
+
}
|
|
68938
|
+
|
|
68939
|
+
// node_modules/circuit-json-to-kicad/dist/index.js
|
|
68488
68940
|
import {
|
|
68941
|
+
Layer,
|
|
68489
68942
|
Pts as Pts3,
|
|
68490
68943
|
Xy as Xy3,
|
|
68491
68944
|
Zone,
|
|
68492
68945
|
ZoneConnectPads,
|
|
68493
68946
|
ZoneFill,
|
|
68947
|
+
ZoneFilledPolygon,
|
|
68494
68948
|
ZoneHatch,
|
|
68495
68949
|
ZonePolygon
|
|
68496
68950
|
} from "kicadts";
|
|
@@ -68576,7 +69030,7 @@ import { Via, ViaNet } from "kicadts";
|
|
|
68576
69030
|
import { applyToPoint as applyToPoint18 } from "transformation-matrix";
|
|
68577
69031
|
import { Footprint as Footprint4 } from "kicadts";
|
|
68578
69032
|
import { applyToPoint as applyToPoint19 } from "transformation-matrix";
|
|
68579
|
-
import { GrLine } from "kicadts";
|
|
69033
|
+
import { GrCircle, GrLine, GrPoly } from "kicadts";
|
|
68580
69034
|
import {
|
|
68581
69035
|
At as At2,
|
|
68582
69036
|
GrText,
|
|
@@ -68585,7 +69039,7 @@ import {
|
|
|
68585
69039
|
TextEffectsJustify as TextEffectsJustify3
|
|
68586
69040
|
} from "kicadts";
|
|
68587
69041
|
import { applyToPoint as applyToPoint20 } from "transformation-matrix";
|
|
68588
|
-
import { applyToPoint as applyToPoint22 } from "transformation-matrix";
|
|
69042
|
+
import { applyToPoint as applyToPoint22, rotate as rotate9 } from "transformation-matrix";
|
|
68589
69043
|
import {
|
|
68590
69044
|
GrText as GrText2,
|
|
68591
69045
|
TextEffects as TextEffects11,
|
|
@@ -68730,8 +69184,9 @@ function getReferencePrefixForComponent(sourceComponent) {
|
|
|
68730
69184
|
}
|
|
68731
69185
|
function getReferenceDesignator(sourceComponent) {
|
|
68732
69186
|
const name = sourceComponent?.name;
|
|
68733
|
-
|
|
68734
|
-
|
|
69187
|
+
const trimmedName = name?.trim();
|
|
69188
|
+
if (trimmedName) {
|
|
69189
|
+
return trimmedName;
|
|
68735
69190
|
}
|
|
68736
69191
|
const prefix = getReferencePrefixForComponent(sourceComponent);
|
|
68737
69192
|
return `${prefix}?`;
|
|
@@ -70329,6 +70784,8 @@ function generateDeterministicUuid(data) {
|
|
|
70329
70784
|
const hash = simpleHash(data);
|
|
70330
70785
|
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
70331
70786
|
}
|
|
70787
|
+
var isPcbCopperPour = (element) => element.type === "pcb_copper_pour";
|
|
70788
|
+
var getCopperPours = (circuitJson) => circuitJson.filter(isPcbCopperPour);
|
|
70332
70789
|
var getCopperPourNetInfo = (pour, ctx) => {
|
|
70333
70790
|
let connectivityKey = pour.source_net_id;
|
|
70334
70791
|
if (connectivityKey) {
|
|
@@ -70339,19 +70796,13 @@ var getCopperPourNetInfo = (pour, ctx) => {
|
|
|
70339
70796
|
return;
|
|
70340
70797
|
return ctx.pcbNetMap?.get(connectivityKey);
|
|
70341
70798
|
};
|
|
70342
|
-
var
|
|
70343
|
-
return (ring.vertices ?? []).map((point) => {
|
|
70344
|
-
const transformedPoint = applyToPoint8(c2kMatPcb, point);
|
|
70345
|
-
return new Xy3(transformedPoint.x, transformedPoint.y);
|
|
70346
|
-
});
|
|
70347
|
-
};
|
|
70348
|
-
var getPolygonPoints = (points, c2kMatPcb) => {
|
|
70799
|
+
var convertPointsToKicadXy = (points, c2kMatPcb) => {
|
|
70349
70800
|
return (points ?? []).map((point) => {
|
|
70350
70801
|
const transformedPoint = applyToPoint8(c2kMatPcb, point);
|
|
70351
70802
|
return new Xy3(transformedPoint.x, transformedPoint.y);
|
|
70352
70803
|
});
|
|
70353
70804
|
};
|
|
70354
|
-
var
|
|
70805
|
+
var rotateRingToStartAtTopRight = (points) => {
|
|
70355
70806
|
if (points.length < 2)
|
|
70356
70807
|
return points;
|
|
70357
70808
|
let startIndex = 0;
|
|
@@ -70366,6 +70817,26 @@ var rotatePointsToTopRight = (points) => {
|
|
|
70366
70817
|
}
|
|
70367
70818
|
return [...points.slice(startIndex), ...points.slice(0, startIndex)];
|
|
70368
70819
|
};
|
|
70820
|
+
var removeConsecutiveDuplicatePoints = (points) => {
|
|
70821
|
+
const dedupedPoints = [];
|
|
70822
|
+
for (const point of points) {
|
|
70823
|
+
const lastPoint = dedupedPoints[dedupedPoints.length - 1];
|
|
70824
|
+
if (lastPoint?.x === point.x && lastPoint.y === point.y) {
|
|
70825
|
+
continue;
|
|
70826
|
+
}
|
|
70827
|
+
dedupedPoints.push(point);
|
|
70828
|
+
}
|
|
70829
|
+
return dedupedPoints;
|
|
70830
|
+
};
|
|
70831
|
+
var removeRepeatedClosingPoint = (points) => {
|
|
70832
|
+
const dedupedPoints = [...points];
|
|
70833
|
+
const firstPoint = dedupedPoints[0];
|
|
70834
|
+
const lastPoint = dedupedPoints[dedupedPoints.length - 1];
|
|
70835
|
+
if (firstPoint && lastPoint && dedupedPoints.length > 1 && firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y) {
|
|
70836
|
+
dedupedPoints.pop();
|
|
70837
|
+
}
|
|
70838
|
+
return dedupedPoints;
|
|
70839
|
+
};
|
|
70369
70840
|
var getRectRingPoints = (pour, c2kMatPcb) => {
|
|
70370
70841
|
const ccwRotationDegrees = pour.rotation ?? 0;
|
|
70371
70842
|
const cornerTransform = compose3(translate3(pour.center.x, pour.center.y), rotate(ccwRotationDegrees * Math.PI / 180));
|
|
@@ -70377,17 +70848,87 @@ var getRectRingPoints = (pour, c2kMatPcb) => {
|
|
|
70377
70848
|
{ x: halfWidth, y: halfHeight },
|
|
70378
70849
|
{ x: -halfWidth, y: halfHeight }
|
|
70379
70850
|
].map((corner) => applyToPoint8(cornerTransform, corner));
|
|
70380
|
-
return
|
|
70851
|
+
return convertPointsToKicadXy(corners, c2kMatPcb);
|
|
70852
|
+
};
|
|
70853
|
+
var getPolygonRingPoints = (pour, c2kMatPcb) => removeRepeatedClosingPoint(removeConsecutiveDuplicatePoints(rotateRingToStartAtTopRight(convertPointsToKicadXy(pour.points, c2kMatPcb))));
|
|
70854
|
+
var getBrepZoneRings = (pour, c2kMatPcb) => [
|
|
70855
|
+
removeRepeatedClosingPoint(removeConsecutiveDuplicatePoints(rotateRingToStartAtTopRight(convertPointsToKicadXy(pour.brep_shape.outer_ring.vertices, c2kMatPcb)))),
|
|
70856
|
+
pour.brep_shape.inner_rings.map((ring) => removeRepeatedClosingPoint(removeConsecutiveDuplicatePoints(rotateRingToStartAtTopRight(convertPointsToKicadXy(ring.vertices, c2kMatPcb))))).filter((ringPoints) => ringPoints.length >= 3)
|
|
70857
|
+
];
|
|
70858
|
+
var getCopperPourZoneRings = (pour, c2kMatPcb) => {
|
|
70859
|
+
switch (pour.shape) {
|
|
70860
|
+
case "rect":
|
|
70861
|
+
return [
|
|
70862
|
+
removeRepeatedClosingPoint(removeConsecutiveDuplicatePoints(rotateRingToStartAtTopRight(getRectRingPoints(pour, c2kMatPcb)))),
|
|
70863
|
+
[]
|
|
70864
|
+
];
|
|
70865
|
+
case "polygon":
|
|
70866
|
+
return [getPolygonRingPoints(pour, c2kMatPcb), []];
|
|
70867
|
+
case "brep":
|
|
70868
|
+
return getBrepZoneRings(pour, c2kMatPcb);
|
|
70869
|
+
}
|
|
70381
70870
|
};
|
|
70382
|
-
var
|
|
70383
|
-
|
|
70384
|
-
|
|
70871
|
+
var createZonePolygons = (outerRing, innerRings) => {
|
|
70872
|
+
const polygons = [];
|
|
70873
|
+
if (outerRing.length >= 3) {
|
|
70874
|
+
polygons.push(new ZonePolygon(new Pts3(outerRing)));
|
|
70385
70875
|
}
|
|
70386
|
-
|
|
70387
|
-
|
|
70876
|
+
for (const innerRing of innerRings) {
|
|
70877
|
+
if (innerRing.length < 3)
|
|
70878
|
+
continue;
|
|
70879
|
+
polygons.push(new ZonePolygon(new Pts3(innerRing)));
|
|
70388
70880
|
}
|
|
70389
|
-
|
|
70390
|
-
|
|
70881
|
+
return polygons;
|
|
70882
|
+
};
|
|
70883
|
+
var getTriangleArea = (a, b, c) => Math.abs((a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2);
|
|
70884
|
+
var createZoneFilledPolygons = (outerRing, innerRings, kicadLayer) => {
|
|
70885
|
+
if (outerRing.length < 3) {
|
|
70886
|
+
return [];
|
|
70887
|
+
}
|
|
70888
|
+
const layer = new Layer([kicadLayer]);
|
|
70889
|
+
if (innerRings.length === 0) {
|
|
70890
|
+
return [
|
|
70891
|
+
new ZoneFilledPolygon({
|
|
70892
|
+
layer,
|
|
70893
|
+
pts: new Pts3(outerRing)
|
|
70894
|
+
})
|
|
70895
|
+
];
|
|
70896
|
+
}
|
|
70897
|
+
const flattenedPoints = [];
|
|
70898
|
+
const holeIndices = [];
|
|
70899
|
+
let pointIndex = 0;
|
|
70900
|
+
const addRing = (ring) => {
|
|
70901
|
+
for (const point of ring) {
|
|
70902
|
+
flattenedPoints.push(point.x, point.y);
|
|
70903
|
+
}
|
|
70904
|
+
pointIndex += ring.length;
|
|
70905
|
+
};
|
|
70906
|
+
addRing(outerRing);
|
|
70907
|
+
for (const innerRing of innerRings) {
|
|
70908
|
+
holeIndices.push(pointIndex);
|
|
70909
|
+
addRing(innerRing);
|
|
70910
|
+
}
|
|
70911
|
+
const triangleIndices = earcut(flattenedPoints, holeIndices, 2);
|
|
70912
|
+
const filledPolygons = [];
|
|
70913
|
+
for (let i = 0;i < triangleIndices.length; i += 3) {
|
|
70914
|
+
const trianglePoints = [];
|
|
70915
|
+
for (let offset = 0;offset < 3; offset++) {
|
|
70916
|
+
const pointOffset = triangleIndices[i + offset] * 2;
|
|
70917
|
+
const x = flattenedPoints[pointOffset];
|
|
70918
|
+
const y = flattenedPoints[pointOffset + 1];
|
|
70919
|
+
if (x === undefined || y === undefined)
|
|
70920
|
+
continue;
|
|
70921
|
+
trianglePoints.push(new Xy3(x, y));
|
|
70922
|
+
}
|
|
70923
|
+
if (trianglePoints.length !== 3 || getTriangleArea(trianglePoints[0], trianglePoints[1], trianglePoints[2]) === 0) {
|
|
70924
|
+
continue;
|
|
70925
|
+
}
|
|
70926
|
+
filledPolygons.push(new ZoneFilledPolygon({
|
|
70927
|
+
layer,
|
|
70928
|
+
pts: new Pts3(trianglePoints)
|
|
70929
|
+
}));
|
|
70930
|
+
}
|
|
70931
|
+
return filledPolygons;
|
|
70391
70932
|
};
|
|
70392
70933
|
var AddCopperPoursStage = class extends ConverterStage {
|
|
70393
70934
|
_step() {
|
|
@@ -70398,19 +70939,18 @@ var AddCopperPoursStage = class extends ConverterStage {
|
|
|
70398
70939
|
if (!c2kMatPcb) {
|
|
70399
70940
|
throw new Error("PCB transformation matrix not initialized in context");
|
|
70400
70941
|
}
|
|
70401
|
-
const copperPours = this.
|
|
70402
|
-
for (const pour of copperPours
|
|
70403
|
-
const
|
|
70404
|
-
if (
|
|
70942
|
+
const copperPours = getCopperPours(this.input);
|
|
70943
|
+
for (const pour of copperPours) {
|
|
70944
|
+
const [outerRing, innerRings] = getCopperPourZoneRings(pour, c2kMatPcb);
|
|
70945
|
+
if (outerRing.length < 3)
|
|
70405
70946
|
continue;
|
|
70406
70947
|
const netInfo = getCopperPourNetInfo(pour, this.ctx);
|
|
70407
70948
|
const kicadLayer = getKicadLayer(pour.layer);
|
|
70408
|
-
const polygonPts = new Pts3(polygonPoints);
|
|
70409
70949
|
const zone = new Zone({
|
|
70410
70950
|
net: netInfo?.id ?? 0,
|
|
70411
70951
|
netName: netInfo?.name ?? "",
|
|
70412
70952
|
layer: kicadLayer,
|
|
70413
|
-
uuid: generateDeterministicUuid(`zone:${pour.pcb_copper_pour_id
|
|
70953
|
+
uuid: generateDeterministicUuid(`zone:${pour.pcb_copper_pour_id}`),
|
|
70414
70954
|
hatch: new ZoneHatch("edge", 0.5),
|
|
70415
70955
|
connectPads: new ZoneConnectPads({ enabled: true, clearance: 0.15 }),
|
|
70416
70956
|
minThickness: 0.25,
|
|
@@ -70418,9 +70958,11 @@ var AddCopperPoursStage = class extends ConverterStage {
|
|
|
70418
70958
|
fill: new ZoneFill({
|
|
70419
70959
|
filled: true,
|
|
70420
70960
|
thermalGap: 0.5,
|
|
70421
|
-
thermalBridgeWidth: 0.5
|
|
70961
|
+
thermalBridgeWidth: 0.5,
|
|
70962
|
+
islandRemovalMode: 0
|
|
70422
70963
|
}),
|
|
70423
|
-
polygons:
|
|
70964
|
+
polygons: createZonePolygons(outerRing, innerRings),
|
|
70965
|
+
filledPolygons: createZoneFilledPolygons(outerRing, innerRings, kicadLayer)
|
|
70424
70966
|
});
|
|
70425
70967
|
const zones = kicadPcb.zones;
|
|
70426
70968
|
zones.push(zone);
|
|
@@ -71090,7 +71632,8 @@ function convertCourtyardRects(courtyardRects, componentCenter) {
|
|
|
71090
71632
|
}
|
|
71091
71633
|
return fpRects;
|
|
71092
71634
|
}
|
|
71093
|
-
function convertCourtyardOutlines(
|
|
71635
|
+
function convertCourtyardOutlines(params2) {
|
|
71636
|
+
const { courtyardOutlines, componentCenter, componentRotation = 0 } = params2;
|
|
71094
71637
|
const fpPolys = [];
|
|
71095
71638
|
const cj2kicadMatrix = compose4(componentRotation !== 0 ? rotate2(componentRotation * Math.PI / 180) : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, scale2(1, -1), translate4(-componentCenter.x, -componentCenter.y));
|
|
71096
71639
|
for (const outline of courtyardOutlines) {
|
|
@@ -71161,7 +71704,13 @@ function createFpTextFromCircuitJson({
|
|
|
71161
71704
|
effects: textEffects
|
|
71162
71705
|
});
|
|
71163
71706
|
}
|
|
71164
|
-
function convertSilkscreenTexts(
|
|
71707
|
+
function convertSilkscreenTexts(params2) {
|
|
71708
|
+
const {
|
|
71709
|
+
silkscreenTexts,
|
|
71710
|
+
componentCenter,
|
|
71711
|
+
componentRotation,
|
|
71712
|
+
sourceComponentName
|
|
71713
|
+
} = params2;
|
|
71165
71714
|
const fpTexts = [];
|
|
71166
71715
|
for (const textElement of silkscreenTexts) {
|
|
71167
71716
|
const fpText = createFpTextFromCircuitJson({
|
|
@@ -71217,7 +71766,8 @@ function convertSilkscreenPaths(silkscreenPaths, { componentCenter, componentRot
|
|
|
71217
71766
|
}
|
|
71218
71767
|
return fpLines;
|
|
71219
71768
|
}
|
|
71220
|
-
function convertNoteTexts(
|
|
71769
|
+
function convertNoteTexts(params2) {
|
|
71770
|
+
const { noteTexts, componentCenter, componentRotation } = params2;
|
|
71221
71771
|
const fpTexts = [];
|
|
71222
71772
|
for (const textElement of noteTexts) {
|
|
71223
71773
|
const relX = textElement.anchor_position.x - componentCenter.x;
|
|
@@ -71247,17 +71797,19 @@ function create3DModelsFromCadComponent(cadComponent, componentCenter, options)
|
|
|
71247
71797
|
const model = new FootprintModel3(modelUrl);
|
|
71248
71798
|
if (cadComponent.position) {
|
|
71249
71799
|
const boardLayerZOffset = options?.boardLayerZOffset ?? 0;
|
|
71800
|
+
const modelOriginPosition = cadComponent.model_origin_position;
|
|
71250
71801
|
model.offset = {
|
|
71251
|
-
x: (cadComponent.position.x || 0) - componentCenter.x,
|
|
71252
|
-
y: (cadComponent.position.y || 0) - componentCenter.y,
|
|
71253
|
-
z: (cadComponent.position.z || 0) - boardLayerZOffset
|
|
71802
|
+
x: (cadComponent.position.x || 0) - componentCenter.x - (modelOriginPosition?.x || 0),
|
|
71803
|
+
y: (cadComponent.position.y || 0) - componentCenter.y - (modelOriginPosition?.y || 0),
|
|
71804
|
+
z: (cadComponent.position.z || 0) - boardLayerZOffset - (modelOriginPosition?.z || 0)
|
|
71254
71805
|
};
|
|
71255
71806
|
}
|
|
71256
71807
|
if (cadComponent.rotation) {
|
|
71808
|
+
const footprintRotation = options?.footprintRotation ?? 0;
|
|
71257
71809
|
model.rotate = {
|
|
71258
71810
|
x: cadComponent.rotation.x || 0,
|
|
71259
71811
|
y: cadComponent.rotation.y || 0,
|
|
71260
|
-
z: cadComponent.rotation.z || 0
|
|
71812
|
+
z: (cadComponent.rotation.z || 0) - footprintRotation
|
|
71261
71813
|
};
|
|
71262
71814
|
}
|
|
71263
71815
|
if (cadComponent.model_unit_to_mm_scale_factor) {
|
|
@@ -71336,6 +71888,15 @@ function createSmdPadFromCircuitJson({
|
|
|
71336
71888
|
}
|
|
71337
71889
|
padSize = [pcbPad.width, pcbPad.height];
|
|
71338
71890
|
rotation = pcbPad.ccw_rotation;
|
|
71891
|
+
} else if (pcbPad.shape === "pill") {
|
|
71892
|
+
padShape = "roundrect";
|
|
71893
|
+
padSize = [pcbPad.width, pcbPad.height];
|
|
71894
|
+
roundrect_rratio = pcbPad.radius / Math.min(pcbPad.width, pcbPad.height);
|
|
71895
|
+
} else if (pcbPad.shape === "rotated_pill") {
|
|
71896
|
+
padShape = "roundrect";
|
|
71897
|
+
padSize = [pcbPad.width, pcbPad.height];
|
|
71898
|
+
roundrect_rratio = pcbPad.radius / Math.min(pcbPad.width, pcbPad.height);
|
|
71899
|
+
rotation = pcbPad.ccw_rotation;
|
|
71339
71900
|
} else if (pcbPad.shape === "rect") {
|
|
71340
71901
|
const cornerRadius = pcbPad.corner_radius ?? pcbPad.rect_border_radius;
|
|
71341
71902
|
if (cornerRadius) {
|
|
@@ -71359,6 +71920,7 @@ function createSmdPadFromCircuitJson({
|
|
|
71359
71920
|
`${padLayer === "F.Cu" ? "F" : "B"}.Mask`
|
|
71360
71921
|
],
|
|
71361
71922
|
solderMaskMargin: pcbPad.soldermask_margin,
|
|
71923
|
+
roundrectRatio: roundrect_rratio,
|
|
71362
71924
|
uuid: generateDeterministicUuid(padData)
|
|
71363
71925
|
});
|
|
71364
71926
|
if (padOptions) {
|
|
@@ -71602,7 +72164,8 @@ function createNpthPadFromCircuitJson({
|
|
|
71602
72164
|
uuid: crypto.randomUUID()
|
|
71603
72165
|
});
|
|
71604
72166
|
}
|
|
71605
|
-
function convertNpthHoles(
|
|
72167
|
+
function convertNpthHoles(params2) {
|
|
72168
|
+
const { pcbHoles, componentCenter, componentRotation } = params2;
|
|
71606
72169
|
const pads = [];
|
|
71607
72170
|
for (const pcbHole of pcbHoles) {
|
|
71608
72171
|
const pad = createNpthPadFromCircuitJson({
|
|
@@ -71675,9 +72238,18 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
71675
72238
|
});
|
|
71676
72239
|
const fpTexts = footprint.fpTexts;
|
|
71677
72240
|
const pcbSilkscreenTexts = this.ctx.db.pcb_silkscreen_text?.list().filter((text) => text.pcb_component_id === component.pcb_component_id) || [];
|
|
71678
|
-
fpTexts.push(...convertSilkscreenTexts(
|
|
72241
|
+
fpTexts.push(...convertSilkscreenTexts({
|
|
72242
|
+
silkscreenTexts: pcbSilkscreenTexts,
|
|
72243
|
+
componentCenter: component.center,
|
|
72244
|
+
componentRotation: component.rotation || 0,
|
|
72245
|
+
sourceComponentName: sourceComponent?.name
|
|
72246
|
+
}));
|
|
71679
72247
|
const pcbNoteTexts = this.ctx.db.pcb_note_text?.list().filter((text) => text.pcb_component_id === component.pcb_component_id) || [];
|
|
71680
|
-
fpTexts.push(...convertNoteTexts(
|
|
72248
|
+
fpTexts.push(...convertNoteTexts({
|
|
72249
|
+
noteTexts: pcbNoteTexts,
|
|
72250
|
+
componentCenter: component.center,
|
|
72251
|
+
componentRotation: component.rotation || 0
|
|
72252
|
+
}));
|
|
71681
72253
|
footprint.fpTexts = fpTexts;
|
|
71682
72254
|
const pcbSilkscreenPaths = this.ctx.db.pcb_silkscreen_path?.list().filter((path7) => path7.pcb_component_id === component.pcb_component_id) || [];
|
|
71683
72255
|
const fpLines = footprint.fpLines ?? [];
|
|
@@ -71709,7 +72281,11 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
71709
72281
|
}, this.ctx);
|
|
71710
72282
|
fpPads.push(...thruHolePads);
|
|
71711
72283
|
const pcbHoles = this.ctx.db.pcb_hole?.list().filter((hole) => hole.pcb_component_id === component.pcb_component_id) || [];
|
|
71712
|
-
const npthPads = convertNpthHoles(
|
|
72284
|
+
const npthPads = convertNpthHoles({
|
|
72285
|
+
pcbHoles,
|
|
72286
|
+
componentCenter: component.center,
|
|
72287
|
+
componentRotation: component.rotation || 0
|
|
72288
|
+
});
|
|
71713
72289
|
fpPads.push(...npthPads);
|
|
71714
72290
|
footprint.fpPads = fpPads;
|
|
71715
72291
|
const pcbSilkscreenCircles = this.ctx.db.pcb_silkscreen_circle?.list().filter((circle) => circle.pcb_component_id === component.pcb_component_id) || [];
|
|
@@ -71727,7 +72303,11 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
71727
72303
|
fpRects.push(...convertCourtyardRects(pcbCourtyardRects, component.center));
|
|
71728
72304
|
footprint.fpRects = fpRects;
|
|
71729
72305
|
const pcbCourtyardOutlines = this.ctx.db.pcb_courtyard_outline?.list().filter((outline) => outline.pcb_component_id === component.pcb_component_id) || [];
|
|
71730
|
-
const fpPolys = convertCourtyardOutlines(
|
|
72306
|
+
const fpPolys = convertCourtyardOutlines({
|
|
72307
|
+
courtyardOutlines: pcbCourtyardOutlines,
|
|
72308
|
+
componentCenter: component.center,
|
|
72309
|
+
componentRotation: component.rotation || 0
|
|
72310
|
+
});
|
|
71731
72311
|
if (fpPolys.length > 0) {
|
|
71732
72312
|
footprint.fpPolys = fpPolys;
|
|
71733
72313
|
}
|
|
@@ -71735,7 +72315,10 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
71735
72315
|
const pcbBoard = this.ctx.db.pcb_board?.list()[0];
|
|
71736
72316
|
const boardThickness = pcbBoard?.thickness ?? 0;
|
|
71737
72317
|
const boardLayerZOffset = component.layer === "bottom" ? -(boardThickness / 2) : boardThickness / 2;
|
|
71738
|
-
const models = create3DModelsFromCadComponent(cadComponent, component.center, {
|
|
72318
|
+
const models = create3DModelsFromCadComponent(cadComponent, component.center, {
|
|
72319
|
+
boardLayerZOffset,
|
|
72320
|
+
footprintRotation: component.rotation || 0
|
|
72321
|
+
});
|
|
71739
72322
|
const KICAD_3D_BASE = "${KIPRJMOD}/3dmodels";
|
|
71740
72323
|
if (models.length > 0) {
|
|
71741
72324
|
if (this.includeBuiltin3dModels) {
|
|
@@ -71789,6 +72372,24 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
71789
72372
|
return this.ctx.kicadPcb;
|
|
71790
72373
|
}
|
|
71791
72374
|
};
|
|
72375
|
+
function getRoutePointLayer(point, pointRoleInSegment) {
|
|
72376
|
+
if ("layer" in point) {
|
|
72377
|
+
return point.layer;
|
|
72378
|
+
}
|
|
72379
|
+
if (point.route_type === "through_pad") {
|
|
72380
|
+
if (pointRoleInSegment === "start") {
|
|
72381
|
+
return point.end_layer;
|
|
72382
|
+
}
|
|
72383
|
+
return point.start_layer;
|
|
72384
|
+
}
|
|
72385
|
+
return;
|
|
72386
|
+
}
|
|
72387
|
+
function getRoutePointWidth(point) {
|
|
72388
|
+
if ("width" in point) {
|
|
72389
|
+
return point.width;
|
|
72390
|
+
}
|
|
72391
|
+
return;
|
|
72392
|
+
}
|
|
71792
72393
|
var AddTracesStage = class extends ConverterStage {
|
|
71793
72394
|
tracesProcessed = 0;
|
|
71794
72395
|
pcbTraces = [];
|
|
@@ -71796,6 +72397,18 @@ var AddTracesStage = class extends ConverterStage {
|
|
|
71796
72397
|
super(input, ctx);
|
|
71797
72398
|
this.pcbTraces = this.ctx.db.pcb_trace.list();
|
|
71798
72399
|
}
|
|
72400
|
+
getRoutePointPosition(point, pointRoleInSegment) {
|
|
72401
|
+
if ("x" in point && "y" in point) {
|
|
72402
|
+
return { x: point.x, y: point.y };
|
|
72403
|
+
}
|
|
72404
|
+
if (point.route_type !== "through_pad") {
|
|
72405
|
+
return null;
|
|
72406
|
+
}
|
|
72407
|
+
if (pointRoleInSegment === "start") {
|
|
72408
|
+
return { x: point.end.x, y: point.end.y };
|
|
72409
|
+
}
|
|
72410
|
+
return { x: point.start.x, y: point.start.y };
|
|
72411
|
+
}
|
|
71799
72412
|
_step() {
|
|
71800
72413
|
const { kicadPcb, c2kMatPcb, pcbNetMap } = this.ctx;
|
|
71801
72414
|
if (!kicadPcb) {
|
|
@@ -71809,22 +72422,25 @@ var AddTracesStage = class extends ConverterStage {
|
|
|
71809
72422
|
return;
|
|
71810
72423
|
}
|
|
71811
72424
|
const trace = this.pcbTraces[this.tracesProcessed];
|
|
71812
|
-
|
|
72425
|
+
const route = trace.route;
|
|
72426
|
+
if (!route || route.length < 2) {
|
|
71813
72427
|
this.tracesProcessed++;
|
|
71814
72428
|
return;
|
|
71815
72429
|
}
|
|
71816
|
-
let lastKnownLayer =
|
|
71817
|
-
for (let i = 0;i <
|
|
71818
|
-
const startPoint =
|
|
71819
|
-
const endPoint =
|
|
71820
|
-
const
|
|
71821
|
-
|
|
71822
|
-
|
|
71823
|
-
|
|
71824
|
-
|
|
71825
|
-
|
|
71826
|
-
|
|
71827
|
-
|
|
72430
|
+
let lastKnownLayer = getRoutePointLayer(route[0], "start");
|
|
72431
|
+
for (let i = 0;i < route.length - 1; i++) {
|
|
72432
|
+
const startPoint = route[i];
|
|
72433
|
+
const endPoint = route[i + 1];
|
|
72434
|
+
const startPosition = this.getRoutePointPosition(startPoint, "start");
|
|
72435
|
+
const endPosition = this.getRoutePointPosition(endPoint, "end");
|
|
72436
|
+
if (!startPosition || !endPosition) {
|
|
72437
|
+
throw new Error(`Unable to convert pcb_trace route segment ${trace.pcb_trace_id ?? this.tracesProcessed}:${i} to KiCad segment`);
|
|
72438
|
+
}
|
|
72439
|
+
const transformedStart = applyToPoint17(c2kMatPcb, startPosition);
|
|
72440
|
+
const transformedEnd = applyToPoint17(c2kMatPcb, endPosition);
|
|
72441
|
+
if (transformedStart.x === transformedEnd.x && transformedStart.y === transformedEnd.y) {
|
|
72442
|
+
continue;
|
|
72443
|
+
}
|
|
71828
72444
|
let netInfo;
|
|
71829
72445
|
if (pcbNetMap) {
|
|
71830
72446
|
let connectivityKey = trace.subcircuit_connectivity_map_key;
|
|
@@ -71853,25 +72469,27 @@ var AddTracesStage = class extends ConverterStage {
|
|
|
71853
72469
|
netInfo = pcbNetMap.get(connectivityKey);
|
|
71854
72470
|
}
|
|
71855
72471
|
}
|
|
71856
|
-
const segmentLayerSource = startPoint
|
|
72472
|
+
const segmentLayerSource = getRoutePointLayer(startPoint, "start") ?? getRoutePointLayer(endPoint, "end") ?? lastKnownLayer;
|
|
71857
72473
|
const kicadLayer = getKicadLayer(segmentLayerSource);
|
|
71858
72474
|
const segmentData = `segment:${transformedStart.x},${transformedStart.y}:${transformedEnd.x},${transformedEnd.y}:${kicadLayer}:${netInfo?.id ?? 0}`;
|
|
71859
72475
|
const segment = new Segment({
|
|
71860
72476
|
start: { x: transformedStart.x, y: transformedStart.y },
|
|
71861
72477
|
end: { x: transformedEnd.x, y: transformedEnd.y },
|
|
71862
72478
|
layer: kicadLayer,
|
|
71863
|
-
width: startPoint
|
|
72479
|
+
width: getRoutePointWidth(startPoint) ?? getRoutePointWidth(endPoint) ?? trace.width ?? 0.25,
|
|
71864
72480
|
net: new SegmentNet(netInfo?.id ?? 0),
|
|
71865
72481
|
uuid: generateDeterministicUuid(segmentData)
|
|
71866
72482
|
});
|
|
71867
72483
|
const segments = kicadPcb.segments;
|
|
71868
72484
|
segments.push(segment);
|
|
71869
72485
|
kicadPcb.segments = segments;
|
|
71870
|
-
|
|
71871
|
-
|
|
72486
|
+
const startLayer = getRoutePointLayer(startPoint, "start");
|
|
72487
|
+
const endLayer = getRoutePointLayer(endPoint, "end");
|
|
72488
|
+
if (startLayer) {
|
|
72489
|
+
lastKnownLayer = startLayer;
|
|
71872
72490
|
}
|
|
71873
|
-
if (
|
|
71874
|
-
lastKnownLayer =
|
|
72491
|
+
if (endLayer) {
|
|
72492
|
+
lastKnownLayer = endLayer;
|
|
71875
72493
|
}
|
|
71876
72494
|
}
|
|
71877
72495
|
this.tracesProcessed++;
|
|
@@ -72071,7 +72689,11 @@ var AddStandalonePcbElements = class extends ConverterStage {
|
|
|
72071
72689
|
uuid: generateDeterministicUuid(footprintSeed)
|
|
72072
72690
|
});
|
|
72073
72691
|
const ccwRotationDegrees = 0;
|
|
72074
|
-
const npthPads = convertNpthHoles(
|
|
72692
|
+
const npthPads = convertNpthHoles({
|
|
72693
|
+
pcbHoles: [hole],
|
|
72694
|
+
componentCenter: { x: hole.x, y: hole.y },
|
|
72695
|
+
componentRotation: ccwRotationDegrees
|
|
72696
|
+
});
|
|
72075
72697
|
if (npthPads.length > 0) {
|
|
72076
72698
|
footprint.fpPads = npthPads;
|
|
72077
72699
|
const footprints = kicadPcb.footprints;
|
|
@@ -72222,7 +72844,8 @@ function createFabricationNoteTextFromCircuitJson({
|
|
|
72222
72844
|
const grText = new GrText({
|
|
72223
72845
|
text: textElement.text,
|
|
72224
72846
|
layer: kicadLayer,
|
|
72225
|
-
effects: textEffects
|
|
72847
|
+
effects: textEffects,
|
|
72848
|
+
uuid: generateDeterministicUuid(textElement.pcb_fabrication_note_text_id ?? textElement.text)
|
|
72226
72849
|
});
|
|
72227
72850
|
grText.position = position;
|
|
72228
72851
|
return grText;
|
|
@@ -72279,7 +72902,8 @@ function createGrTextFromCircuitJson({
|
|
|
72279
72902
|
const grText = new GrText2({
|
|
72280
72903
|
text: textElement.text,
|
|
72281
72904
|
layer: kicadLayer,
|
|
72282
|
-
effects: textEffects
|
|
72905
|
+
effects: textEffects,
|
|
72906
|
+
uuid: generateDeterministicUuid(textElement.pcb_silkscreen_text_id ?? textElement.text)
|
|
72283
72907
|
});
|
|
72284
72908
|
grText.position = position;
|
|
72285
72909
|
return grText;
|
|
@@ -72298,6 +72922,44 @@ var normalizeOutlineCorners = (corners) => {
|
|
|
72298
72922
|
}
|
|
72299
72923
|
return dedupedCorners;
|
|
72300
72924
|
};
|
|
72925
|
+
var EDGE_CUTS_WIDTH = 0.1;
|
|
72926
|
+
var appendGraphicLine = (kicadPcb, grLine) => {
|
|
72927
|
+
const graphicLines = kicadPcb.graphicLines;
|
|
72928
|
+
graphicLines.push(grLine);
|
|
72929
|
+
kicadPcb.graphicLines = graphicLines;
|
|
72930
|
+
};
|
|
72931
|
+
var appendGraphicCircle = (kicadPcb, grCircle) => {
|
|
72932
|
+
const graphicCircles = kicadPcb.graphicCircles;
|
|
72933
|
+
graphicCircles.push(grCircle);
|
|
72934
|
+
kicadPcb.graphicCircles = graphicCircles;
|
|
72935
|
+
};
|
|
72936
|
+
var appendGraphicPoly = (kicadPcb, grPoly) => {
|
|
72937
|
+
const graphicPolys = kicadPcb.graphicPolys;
|
|
72938
|
+
graphicPolys.push(grPoly);
|
|
72939
|
+
kicadPcb.graphicPolys = graphicPolys;
|
|
72940
|
+
};
|
|
72941
|
+
var rotatePointAroundOrigin = (point, rotationDegrees = 0) => {
|
|
72942
|
+
if (!rotationDegrees)
|
|
72943
|
+
return point;
|
|
72944
|
+
return applyToPoint22(rotate9(rotationDegrees * Math.PI / 180), point);
|
|
72945
|
+
};
|
|
72946
|
+
var getRectCutoutCorners = (cutout) => {
|
|
72947
|
+
const halfWidth = cutout.width / 2;
|
|
72948
|
+
const halfHeight = cutout.height / 2;
|
|
72949
|
+
const localCorners = [
|
|
72950
|
+
{ x: -halfWidth, y: -halfHeight },
|
|
72951
|
+
{ x: halfWidth, y: -halfHeight },
|
|
72952
|
+
{ x: halfWidth, y: halfHeight },
|
|
72953
|
+
{ x: -halfWidth, y: halfHeight }
|
|
72954
|
+
];
|
|
72955
|
+
return localCorners.map((point) => {
|
|
72956
|
+
const rotatedPoint = rotatePointAroundOrigin(point, cutout.rotation);
|
|
72957
|
+
return {
|
|
72958
|
+
x: rotatedPoint.x + cutout.center.x,
|
|
72959
|
+
y: rotatedPoint.y + cutout.center.y
|
|
72960
|
+
};
|
|
72961
|
+
});
|
|
72962
|
+
};
|
|
72301
72963
|
var AddGraphicsStage = class extends ConverterStage {
|
|
72302
72964
|
_step() {
|
|
72303
72965
|
const { kicadPcb, c2kMatPcb } = this.ctx;
|
|
@@ -72335,9 +72997,7 @@ var AddGraphicsStage = class extends ConverterStage {
|
|
|
72335
72997
|
layer: kicadLayer,
|
|
72336
72998
|
width: path7.stroke_width || 0.15
|
|
72337
72999
|
});
|
|
72338
|
-
|
|
72339
|
-
graphicLines.push(grLine);
|
|
72340
|
-
kicadPcb.graphicLines = graphicLines;
|
|
73000
|
+
appendGraphicLine(kicadPcb, grLine);
|
|
72341
73001
|
}
|
|
72342
73002
|
}
|
|
72343
73003
|
const standaloneSilkscreenTexts = this.ctx.db.pcb_silkscreen_text?.list().filter((text) => !text.pcb_component_id) || [];
|
|
@@ -72400,11 +73060,62 @@ var AddGraphicsStage = class extends ConverterStage {
|
|
|
72400
73060
|
start: { x: start.x, y: start.y },
|
|
72401
73061
|
end: { x: end.x, y: end.y },
|
|
72402
73062
|
layer: "Edge.Cuts",
|
|
72403
|
-
width:
|
|
73063
|
+
width: EDGE_CUTS_WIDTH
|
|
73064
|
+
});
|
|
73065
|
+
appendGraphicLine(kicadPcb, edgeLine);
|
|
73066
|
+
}
|
|
73067
|
+
}
|
|
73068
|
+
const pcbCutouts = this.ctx.db.pcb_cutout?.list() || [];
|
|
73069
|
+
for (const cutout of pcbCutouts) {
|
|
73070
|
+
if (cutout.shape === "circle") {
|
|
73071
|
+
const transformedCenter = applyToPoint22(c2kMatPcb, cutout.center);
|
|
73072
|
+
const transformedEnd = applyToPoint22(c2kMatPcb, {
|
|
73073
|
+
x: cutout.center.x + cutout.radius,
|
|
73074
|
+
y: cutout.center.y
|
|
72404
73075
|
});
|
|
72405
|
-
|
|
72406
|
-
|
|
72407
|
-
|
|
73076
|
+
appendGraphicCircle(kicadPcb, new GrCircle({
|
|
73077
|
+
center: transformedCenter,
|
|
73078
|
+
end: transformedEnd,
|
|
73079
|
+
layer: "Edge.Cuts",
|
|
73080
|
+
width: EDGE_CUTS_WIDTH
|
|
73081
|
+
}));
|
|
73082
|
+
} else if (cutout.shape === "polygon") {
|
|
73083
|
+
const corners = normalizeOutlineCorners(cutout.points);
|
|
73084
|
+
if (corners.length < 3)
|
|
73085
|
+
continue;
|
|
73086
|
+
appendGraphicPoly(kicadPcb, new GrPoly({
|
|
73087
|
+
points: corners.map((point) => applyToPoint22(c2kMatPcb, point)),
|
|
73088
|
+
layer: "Edge.Cuts",
|
|
73089
|
+
width: EDGE_CUTS_WIDTH,
|
|
73090
|
+
fill: false
|
|
73091
|
+
}));
|
|
73092
|
+
} else if (cutout.shape === "rect") {
|
|
73093
|
+
const corners = normalizeOutlineCorners(getRectCutoutCorners(cutout));
|
|
73094
|
+
if (corners.length < 3)
|
|
73095
|
+
continue;
|
|
73096
|
+
appendGraphicPoly(kicadPcb, new GrPoly({
|
|
73097
|
+
points: corners.map((point) => applyToPoint22(c2kMatPcb, point)),
|
|
73098
|
+
layer: "Edge.Cuts",
|
|
73099
|
+
width: EDGE_CUTS_WIDTH,
|
|
73100
|
+
fill: false
|
|
73101
|
+
}));
|
|
73102
|
+
} else if (cutout.shape === "path") {
|
|
73103
|
+
if (!cutout.route || cutout.route.length < 2)
|
|
73104
|
+
continue;
|
|
73105
|
+
for (let i = 0;i < cutout.route.length - 1; i++) {
|
|
73106
|
+
const startPoint = cutout.route[i];
|
|
73107
|
+
const endPoint = cutout.route[i + 1];
|
|
73108
|
+
if (!startPoint || !endPoint)
|
|
73109
|
+
continue;
|
|
73110
|
+
const transformedStart = applyToPoint22(c2kMatPcb, startPoint);
|
|
73111
|
+
const transformedEnd = applyToPoint22(c2kMatPcb, endPoint);
|
|
73112
|
+
appendGraphicLine(kicadPcb, new GrLine({
|
|
73113
|
+
start: transformedStart,
|
|
73114
|
+
end: transformedEnd,
|
|
73115
|
+
layer: "Edge.Cuts",
|
|
73116
|
+
width: EDGE_CUTS_WIDTH
|
|
73117
|
+
}));
|
|
73118
|
+
}
|
|
72408
73119
|
}
|
|
72409
73120
|
}
|
|
72410
73121
|
this.finished = true;
|